mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
First pass at hybrid GC mode. This will try use retain-release mode if the collector is not running. Code will run in retain/release mode unless something compiled with -fobjc-gc-only is loaded.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@33174 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
86fa2414ec
commit
4db587f9d6
3 changed files with 131 additions and 23 deletions
|
@ -34,12 +34,18 @@
|
|||
#import "Foundation/NSException.h"
|
||||
#import "Foundation/NSThread.h"
|
||||
|
||||
#if GS_WITH_GC || __OBJC_GC__
|
||||
|
||||
#if GS_WITH_GC || __OBJC_GC__
|
||||
|
||||
#if __OBJC_GC__
|
||||
@interface GSAutoreleasePool : NSAutoreleasePool @end
|
||||
#endif
|
||||
|
||||
@implementation NSAutoreleasePool
|
||||
|
||||
static NSAutoreleasePool *pool = nil;
|
||||
|
||||
#if GS_WITH_GC
|
||||
+ (void) initialize
|
||||
{
|
||||
pool = NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
|
@ -55,6 +61,42 @@ static NSAutoreleasePool *pool = nil;
|
|||
{
|
||||
return pool;
|
||||
}
|
||||
#endif
|
||||
#ifdef __OBJC_GC__
|
||||
|
||||
static Class PoolClass;
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
if ([NSGarbageCollector defaultCollector])
|
||||
{
|
||||
pool = NSAllocateObject(self, 0, NSDefaultMallocZone());
|
||||
}
|
||||
else
|
||||
{
|
||||
PoolClass = [GSAutoreleasePool class];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
+ (id) allocWithZone: (NSZone*)zone
|
||||
{
|
||||
if (nil == pool)
|
||||
{
|
||||
return NSAllocateObject(PoolClass, 0, 0);
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
|
||||
+ (id) new
|
||||
{
|
||||
if (nil == pool)
|
||||
{
|
||||
return [NSAllocateObject(PoolClass, 0, 0) init];
|
||||
}
|
||||
return pool;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (id) init
|
||||
{
|
||||
|
@ -165,7 +207,9 @@ static NSAutoreleasePool *pool = nil;
|
|||
|
||||
@end
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if !GS_WITH_GC
|
||||
|
||||
/* When this is `NO', autoreleased objects are never actually recorded
|
||||
in an NSAutoreleasePool, and are not sent a `release' message.
|
||||
|
@ -249,7 +293,11 @@ pop_pool_from_cache (struct autorelease_thread_vars *tv)
|
|||
}
|
||||
|
||||
|
||||
#if __OBJC_GC__
|
||||
@implementation GSAutoreleasePool
|
||||
#else
|
||||
@implementation NSAutoreleasePool
|
||||
#endif
|
||||
|
||||
+ (void) initialize
|
||||
{
|
||||
|
|
|
@ -64,6 +64,10 @@
|
|||
#endif
|
||||
#endif // __GNUC__
|
||||
|
||||
#ifdef __OBJC_GC__
|
||||
#include <objc/objc-auto.h>
|
||||
#endif
|
||||
|
||||
#define IN_NSOBJECT_M 1
|
||||
#import "GSPrivate.h"
|
||||
|
||||
|
@ -125,7 +129,7 @@ BOOL NSDeallocateZombies = NO;
|
|||
static Class zombieClass = Nil;
|
||||
static NSMapTable *zombieMap = 0;
|
||||
|
||||
#if !GS_WITH_GC && !__OBJC_GC__
|
||||
#if !GS_WITH_GC
|
||||
static void GSMakeZombie(NSObject *o)
|
||||
{
|
||||
Class c;
|
||||
|
@ -421,7 +425,26 @@ struct obj_layout {
|
|||
};
|
||||
typedef struct obj_layout *obj;
|
||||
|
||||
#ifdef __OBJC_GC__
|
||||
|
||||
/**
|
||||
* If -base is compiled in GC mode, then we want to still support manual
|
||||
* reference counting if we are linked with non-GC code.
|
||||
*/
|
||||
static BOOL GSDecrementExtraRefCountWasZero(id anObject);
|
||||
|
||||
BOOL
|
||||
NSDecrementExtraRefCountWasZero(id anObject)
|
||||
{
|
||||
if (!objc_collecting_enabled())
|
||||
{
|
||||
return GSDecrementExtraRefCountWasZero(anObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static BOOL GSDecrementExtraRefCountWasZero(id anObject)
|
||||
#else
|
||||
/**
|
||||
* Examines the extra reference count for the object and, if non-zero
|
||||
* decrements it, otherwise leaves it unchanged.<br />
|
||||
|
@ -431,8 +454,9 @@ typedef struct obj_layout *obj;
|
|||
*/
|
||||
BOOL
|
||||
NSDecrementExtraRefCountWasZero(id anObject)
|
||||
#endif
|
||||
{
|
||||
#if !GS_WITH_GC && !__OBJC_GC__
|
||||
#if !GS_WITH_GC
|
||||
if (double_release_check_enabled)
|
||||
{
|
||||
NSUInteger release_count;
|
||||
|
@ -506,13 +530,38 @@ NSDecrementExtraRefCountWasZero(id anObject)
|
|||
inline NSUInteger
|
||||
NSExtraRefCount(id anObject)
|
||||
{
|
||||
#if GS_WITH_GC || __OBJC_GC__
|
||||
#ifdef __OBJC_GC__
|
||||
if (objc_collecting_enabled())
|
||||
{
|
||||
return UINT_MAX-1;
|
||||
}
|
||||
#endif
|
||||
#if GS_WITH_GC
|
||||
return UINT_MAX - 1;
|
||||
#else /* GS_WITH_GC */
|
||||
return ((obj)anObject)[-1].retained;
|
||||
#endif /* GS_WITH_GC */
|
||||
}
|
||||
|
||||
#ifdef __OBJC_GC__
|
||||
|
||||
/**
|
||||
* If -base is compiled in GC mode, then we want to still support manual
|
||||
* reference counting if we are linked with non-GC code.
|
||||
*/
|
||||
static void GSIncrementExtraRefCount(id anObject);
|
||||
|
||||
inline void NSIncrementExtraRefCount(id anObject)
|
||||
{
|
||||
if (!objc_collecting_enabled())
|
||||
{
|
||||
GSIncrementExtraRefCount(anObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void GSIncrementExtraRefCount(id anObject)
|
||||
#else
|
||||
/**
|
||||
* Increments the extra reference count for anObject.<br />
|
||||
* The GNUstep version raises an exception if the reference count
|
||||
|
@ -521,6 +570,7 @@ NSExtraRefCount(id anObject)
|
|||
*/
|
||||
inline void
|
||||
NSIncrementExtraRefCount(id anObject)
|
||||
#endif
|
||||
{
|
||||
#if GS_WITH_GC || __OBJC_GC__
|
||||
return;
|
||||
|
@ -1947,7 +1997,7 @@ objc_create_block_classes_as_subclasses_of(Class super);
|
|||
*/
|
||||
- (oneway void) release
|
||||
{
|
||||
#if (GS_WITH_GC == 0) && !__OBJC_GC__
|
||||
#if (GS_WITH_GC == 0)
|
||||
if (NSDecrementExtraRefCountWasZero(self))
|
||||
{
|
||||
[self dealloc];
|
||||
|
@ -1997,7 +2047,7 @@ objc_create_block_classes_as_subclasses_of(Class super);
|
|||
*/
|
||||
- (id) retain
|
||||
{
|
||||
#if (GS_WITH_GC == 0) && !__OBJC_GC__
|
||||
#if (GS_WITH_GC == 0)
|
||||
NSIncrementExtraRefCount(self);
|
||||
#endif
|
||||
return self;
|
||||
|
@ -2024,7 +2074,7 @@ objc_create_block_classes_as_subclasses_of(Class super);
|
|||
*/
|
||||
- (NSUInteger) retainCount
|
||||
{
|
||||
#if GS_WITH_GC || __OBJC_GC__
|
||||
#if GS_WITH_GC
|
||||
return UINT_MAX;
|
||||
#else
|
||||
return NSExtraRefCount(self) + 1;
|
||||
|
|
|
@ -234,6 +234,10 @@ NSZoneName (NSZone *zone)
|
|||
__strong void *
|
||||
NSAllocateCollectable(NSUInteger size, NSUInteger options)
|
||||
{
|
||||
if (!objc_collecting_enabled())
|
||||
{
|
||||
return calloc(1, size);
|
||||
}
|
||||
id obj = objc_gc_allocate_collectable(size,
|
||||
((options & NSScannedOption) == NSScannedOption));
|
||||
if ((options & NSCollectorDisabledOption) == NSCollectorDisabledOption)
|
||||
|
@ -246,19 +250,26 @@ NSAllocateCollectable(NSUInteger size, NSUInteger options)
|
|||
__strong void *
|
||||
NSReallocateCollectable(void *ptr, NSUInteger size, NSUInteger options)
|
||||
{
|
||||
if (!objc_collecting_enabled())
|
||||
{
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
return objc_gc_reallocate_collectable(ptr, size,
|
||||
((options & NSScannedOption) == NSScannedOption));
|
||||
}
|
||||
|
||||
id NSMakeCollectable(id obj)
|
||||
{
|
||||
objc_gc_release(obj);
|
||||
if (objc_collecting_enabled())
|
||||
{
|
||||
objc_gc_release(obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
NSZone*
|
||||
NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
|
||||
{
|
||||
NSLog(@" *** Creating a zone while running GC is ignored.");
|
||||
return &default_zone;
|
||||
}
|
||||
|
||||
|
@ -268,15 +279,6 @@ NSDefaultMallocZone (void)
|
|||
return &default_zone;
|
||||
}
|
||||
|
||||
// This is an ugly hack. We should be using NSAllocateCollectable() without
|
||||
// NSScannedOption, not trying to fudge this with stuff that's totally
|
||||
// incompatible with Apple's design.
|
||||
NSZone*
|
||||
GSAtomicMallocZone (void)
|
||||
{
|
||||
return &default_zone;
|
||||
}
|
||||
|
||||
NSZone*
|
||||
NSZoneFromPointer (void *ptr)
|
||||
{
|
||||
|
@ -318,15 +320,23 @@ NSZoneMalloc (NSZone *zone, NSUInteger size)
|
|||
void*
|
||||
NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes)
|
||||
{
|
||||
// FIXME: Overflow checking
|
||||
size_t size = elems * bytes;
|
||||
return objc_gc_allocate_collectable(size, YES);
|
||||
if (objc_collecting_enabled())
|
||||
{
|
||||
// FIXME: Overflow checking
|
||||
size_t size = elems * bytes;
|
||||
return objc_gc_allocate_collectable(size, YES);
|
||||
}
|
||||
return calloc(elems, bytes);
|
||||
}
|
||||
|
||||
void*
|
||||
NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size)
|
||||
{
|
||||
return objc_gc_reallocate_collectable(ptr, size, YES);
|
||||
if (objc_collecting_enabled())
|
||||
{
|
||||
return objc_gc_reallocate_collectable(ptr, size, YES);
|
||||
}
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
void NSZoneFree (NSZone *zone, void *ptr) { }
|
||||
|
|
Loading…
Reference in a new issue