mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
more GC improvements
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28220 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
4fa65f0c82
commit
cfb566ed22
10 changed files with 415 additions and 118 deletions
24
ChangeLog
24
ChangeLog
|
@ -1,7 +1,31 @@
|
||||||
|
2009-04-13 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/GSString.m: Change placeholder string initialisation so that,
|
||||||
|
in a GC world, it checks to see if the buffer passed to it is
|
||||||
|
collectable and forces a copy if it isn't. This prevents memory leaks
|
||||||
|
when a malloc'ed buffer is passed to the initialiser.
|
||||||
|
|
||||||
|
2009-04-11 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/GSPrivate.h: New private functions.
|
||||||
|
* Source/NSObject.m: Add function to swizzle isa pointer safely.
|
||||||
|
* Source/NSZone.m: Add function to check for collectable memory.
|
||||||
|
* Source/NSData.m: Add finalisation for shared memory and mapped
|
||||||
|
files. Add finalized subclasses to deal with memory which must be
|
||||||
|
freed when the NSData is collected.
|
||||||
|
|
||||||
2009-04-11 01:12-EDT Gregory John Casamento <greg_casamento@yahoo.com>
|
2009-04-11 01:12-EDT Gregory John Casamento <greg_casamento@yahoo.com>
|
||||||
|
|
||||||
* Source/NSLock.m: Move the warning to a debug log.
|
* Source/NSLock.m: Move the warning to a debug log.
|
||||||
|
|
||||||
|
2009-04-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/cifframe.m:
|
||||||
|
* Source/callrame.m:
|
||||||
|
Update for GC to use scanned memory to hold pointers we got from
|
||||||
|
the stack so that memory will persist as long as the invocation
|
||||||
|
needs it.
|
||||||
|
|
||||||
2009-04-10 Richard Frith-Macdonald <rfm@gnu.org>
|
2009-04-10 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/GSPrivate.h:
|
* Source/GSPrivate.h:
|
||||||
|
|
|
@ -31,16 +31,123 @@
|
||||||
|
|
||||||
/**** Included Headers *******************************************************/
|
/**** Included Headers *******************************************************/
|
||||||
|
|
||||||
#import <Foundation/NSObject.h>
|
#import <Foundation/NSEnumerator.h>
|
||||||
|
#import <Foundation/NSPointerFunctions.h>
|
||||||
#import <Foundation/NSString.h>
|
#import <Foundation/NSString.h>
|
||||||
#import <Foundation/NSArray.h>
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
@class NSArray, NSSet, NSHashTable;
|
||||||
|
|
||||||
/**** Type, Constant, and Macro Definitions **********************************/
|
/**** Type, Constant, and Macro Definitions **********************************/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NSHashTableStrongMemory
|
||||||
|
= NSPointerFunctionsStrongMemory,
|
||||||
|
NSHashTableZeroingWeakMemory
|
||||||
|
= NSPointerFunctionsZeroingWeakMemory,
|
||||||
|
NSHashTableCopyIn
|
||||||
|
= NSPointerFunctionsCopyIn,
|
||||||
|
NSHashTableObjectPointerPersonality
|
||||||
|
= NSPointerFunctionsObjectPointerPersonality,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef NSUInteger NSHashTableOptions;
|
||||||
|
|
||||||
|
@interface NSHashTable : NSObject <NSCopying, NSCoding, NSFastEnumeration>
|
||||||
|
|
||||||
|
+ (id) hashTableWithOptions: (NSPointerFunctionsOptions)options;
|
||||||
|
|
||||||
|
+ (id) hashTableWithWeakObjects;
|
||||||
|
|
||||||
|
- (id) initWithOptions: (NSPointerFunctionsOptions)options
|
||||||
|
capacity: (NSUInteger)initialCapacity;
|
||||||
|
|
||||||
|
- (id) initWithPointerFunctions: (NSPointerFunctions*)functions
|
||||||
|
capacity: (NSUInteger)initialCapacity;
|
||||||
|
|
||||||
|
/** Adds the object to the receiver.
|
||||||
|
*/
|
||||||
|
- (void) addObject: (id)object;
|
||||||
|
|
||||||
|
/** Returns an array containing all objects in the receiver.
|
||||||
|
*/
|
||||||
|
- (NSArray*) allObjects;
|
||||||
|
|
||||||
|
/** Returns any objct from the receiver, or nil if the receiver contains no
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
- (id) anyObject;
|
||||||
|
|
||||||
|
/** Returns YES if the receiver contains an item equal to anObject, or NO
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
- (BOOL) containsObject: (id)anObject;
|
||||||
|
|
||||||
|
/** Return the number of items atored in the receiver.
|
||||||
|
*/
|
||||||
|
- (NSUInteger) count;
|
||||||
|
|
||||||
|
/** Removes from the receiver any items which are not also present in 'other'.
|
||||||
|
*/
|
||||||
|
- (void) intersectHashTable: (NSHashTable*)other;
|
||||||
|
|
||||||
|
/** Returns YES if the receiver and 'other' contain any items in common.
|
||||||
|
*/
|
||||||
|
- (BOOL) intersectsHashTable: (NSHashTable*)other;
|
||||||
|
|
||||||
|
/** Returns YES if the receiver and 'other' contain equal sets of items.
|
||||||
|
*/
|
||||||
|
- (BOOL) isEqualToHashTable: (NSHashTable*)other;
|
||||||
|
|
||||||
|
/** Returns YES fi all the items in the receiver are also present in 'other'
|
||||||
|
*/
|
||||||
|
- (BOOL) isSubsetOfHashTable: (NSHashTable*)other;
|
||||||
|
|
||||||
|
/** Returns an item stored in the receiver which is equal to the supplied
|
||||||
|
* object argument, or nil if no matchi is found.
|
||||||
|
*/
|
||||||
|
- (id) member: (id)object;
|
||||||
|
|
||||||
|
/** Removes from the receivr all those items which are prsent in both
|
||||||
|
* the receiver and in 'other'.
|
||||||
|
*/
|
||||||
|
- (void) minusHashTable: (NSHashTable*)other;
|
||||||
|
|
||||||
|
/** Return an enumerator for the receiver.
|
||||||
|
*/
|
||||||
|
- (NSEnumerator*) objectEnumerator;
|
||||||
|
|
||||||
|
/** Return an NSPointerFunctions value describing the functions used by the
|
||||||
|
* receiver to handle its contents.
|
||||||
|
*/
|
||||||
|
- (NSPointerFunctions*) pointerFunctions;
|
||||||
|
|
||||||
|
/** Removes all objects.
|
||||||
|
*/
|
||||||
|
- (void) removeAllObjects;
|
||||||
|
|
||||||
|
/** Remove the object (or any equal object) from the receiver.
|
||||||
|
*/
|
||||||
|
- (void) removeObject: (id)object;
|
||||||
|
|
||||||
|
/** Returns a set containing all the objects in the receiver.
|
||||||
|
*/
|
||||||
|
- (NSSet*) setRepresentation;
|
||||||
|
|
||||||
|
/** Adds to the receiver thse items present in 'other' which were
|
||||||
|
* not present in the receiver.
|
||||||
|
*/
|
||||||
|
- (void) unionHashTable: (NSHashTable*)other;
|
||||||
|
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash table type ... an opaque pointer to a data structure.
|
* Hash table type ... an opaque pointer to a data structure.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -62,28 +62,6 @@ typedef struct _NSZone NSZone;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* Primary structure representing an <code>NSZone</code>. Technically it
|
|
||||||
* consists of a set of function pointers for zone upkeep functions plus some
|
|
||||||
* other things-
|
|
||||||
<example>
|
|
||||||
{
|
|
||||||
// Functions for zone.
|
|
||||||
void *(*malloc)(struct _NSZone *zone, size_t size);
|
|
||||||
void *(*realloc)(struct _NSZone *zone, void *ptr, size_t size);
|
|
||||||
void (*free)(struct _NSZone *zone, void *ptr);
|
|
||||||
void (*recycle)(struct _NSZone *zone);
|
|
||||||
BOOL (*check)(struct _NSZone *zone);
|
|
||||||
BOOL (*lookup)(struct _NSZone *zone, void *ptr);
|
|
||||||
|
|
||||||
// Zone statistics (not always maintained).
|
|
||||||
struct NSZoneStats (*stats)(struct _NSZone *zone);
|
|
||||||
|
|
||||||
size_t gran; // Zone granularity (passed in on initialization)
|
|
||||||
NSString *name; // Name of zone (default is 'nil')
|
|
||||||
NSZone *next; // Pointer used for internal management of multiple zones.
|
|
||||||
}</example>
|
|
||||||
*/
|
|
||||||
struct _NSZone
|
struct _NSZone
|
||||||
{
|
{
|
||||||
/* Functions for zone. */
|
/* Functions for zone. */
|
||||||
|
@ -100,41 +78,68 @@ struct _NSZone
|
||||||
NSZone *next;
|
NSZone *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* never freed, meaning allocation will be very fast. The whole zone can
|
||||||
|
* still be freed with NSRecycleZone(), and you should still call NSZoneFree
|
||||||
|
* on memory in the zone that is no longer needed, since a count of allocated
|
||||||
|
* pointers is kept and must reach zero before freeing the zone.<br />
|
||||||
|
* If Garbage Collection is enabled, this function does nothing other than
|
||||||
|
* log a warning and return the same value as the NSDefaultMallocZone()
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
GS_EXPORT NSZone*
|
GS_EXPORT NSZone*
|
||||||
NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree);
|
NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree);
|
||||||
|
|
||||||
|
/** Returns the default zone for memory allocation. Memory created in this
|
||||||
|
* zone is the same as memory allocates using the system malloc() function.
|
||||||
|
*/
|
||||||
GS_EXPORT NSZone*
|
GS_EXPORT NSZone*
|
||||||
NSDefaultMallocZone (void);
|
NSDefaultMallocZone (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches and finds the zone ptr was allocated from. The speed depends
|
||||||
|
* upon the number of zones and their size.<br />
|
||||||
|
* If Garbage Collection is enabled, this function always returns the
|
||||||
|
* same as the NSDefaultMallocZone() function.
|
||||||
|
*/
|
||||||
GS_EXPORT NSZone*
|
GS_EXPORT NSZone*
|
||||||
NSZoneFromPointer (void *ptr);
|
NSZoneFromPointer (void *ptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates and returns memory for elems items of size bytes, in the
|
* Allocates and returns memory for elems items of size bytes, in the
|
||||||
* given zone. Returns NULL if allocation of size 0 requested. Raises
|
* given zone. Returns NULL if allocation of size 0 requested. Raises
|
||||||
* <code>NSMallocException</code> if not enough free memory in zone to
|
* <code>NSMallocException</code> if not enough free memory in zone to
|
||||||
* allocate and no more can be obtained from system, unless using the
|
* allocate and no more can be obtained from system, unless using the
|
||||||
* default zone, in which case NULL is returned.
|
* default zone, in which case NULL is returned.<br \>
|
||||||
|
* If Garbage Collection is enabled, this function always allocates
|
||||||
|
* non-scanned, non-collectable memory in the NSDefaultMallocZone() and
|
||||||
|
* the zone argument is ignored.
|
||||||
*/
|
*/
|
||||||
GS_EXPORT void*
|
GS_EXPORT void*
|
||||||
NSZoneMalloc (NSZone *zone, NSUInteger size);
|
NSZoneMalloc (NSZone *zone, NSUInteger size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates and returns cleared memory for elems items of size bytes, in the
|
* Allocates and returns cleared memory for elems items of size bytes, in the
|
||||||
* given zone. Returns NULL if allocation of size 0 requested. Raises
|
* given zone. Returns NULL if allocation of size 0 requested. Raises
|
||||||
* <code>NSMallocException</code> if not enough free memory in zone to
|
* <code>NSMallocException</code> if not enough free memory in zone to
|
||||||
* allocate and no more can be obtained from system, unless using the
|
* allocate and no more can be obtained from system, unless using the
|
||||||
* default zone, in which case NULL is returned.
|
* default zone, in which case NULL is returned.<br />
|
||||||
|
* If Garbage Collection is enabled, this function always allocates
|
||||||
|
* non-scanned, non-collectable memory in the NSDefaultMallocZone() and
|
||||||
|
* the zone argument is ignored.
|
||||||
*/
|
*/
|
||||||
GS_EXPORT void*
|
GS_EXPORT void*
|
||||||
NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes);
|
NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reallocates the chunk of memory in zone pointed to by ptr to a new one of
|
* Reallocates the chunk of memory in zone pointed to by ptr to a new one of
|
||||||
* size bytes. Existing contents in ptr are copied over. Raises an
|
* size bytes. Existing contents in ptr are copied over. Raises an
|
||||||
* <code>NSMallocException</code> if insufficient memory is available in the
|
* <code>NSMallocException</code> if insufficient memory is available in the
|
||||||
* zone and no more memory can be obtained from the system, unless using the
|
* zone and no more memory can be obtained from the system, unless using the
|
||||||
* default zone, in which case NULL is returned.
|
* default zone, in which case NULL is returned.<br />
|
||||||
|
* If Garbage Collection is enabled, the zone argument is ignored.
|
||||||
*/
|
*/
|
||||||
GS_EXPORT void*
|
GS_EXPORT void*
|
||||||
NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size);
|
NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size);
|
||||||
|
@ -144,7 +149,8 @@ NSZoneRealloc (NSZone *zone, void *ptr, NSUInteger size);
|
||||||
* unless all memory in the zone has been explicitly freed (by calls to
|
* unless all memory in the zone has been explicitly freed (by calls to
|
||||||
* NSZoneFree()). For "non-freeable" zones, the number of NSZoneFree() calls
|
* NSZoneFree()). For "non-freeable" zones, the number of NSZoneFree() calls
|
||||||
* must simply equal the number of allocation calls. The default zone, on the
|
* must simply equal the number of allocation calls. The default zone, on the
|
||||||
* other hand, cannot be recycled.
|
* other hand, cannot be recycled.<br />
|
||||||
|
* If Garbage Collection is enabled, this function has not effect.
|
||||||
*/
|
*/
|
||||||
GS_EXPORT void
|
GS_EXPORT void
|
||||||
NSRecycleZone (NSZone *zone);
|
NSRecycleZone (NSZone *zone);
|
||||||
|
@ -153,7 +159,9 @@ NSRecycleZone (NSZone *zone);
|
||||||
* Frees memory pointed to by ptr (which should have been allocated by a
|
* Frees memory pointed to by ptr (which should have been allocated by a
|
||||||
* previous call to NSZoneMalloc(), NSZoneCalloc(), or NSZoneRealloc()) and
|
* previous call to NSZoneMalloc(), NSZoneCalloc(), or NSZoneRealloc()) and
|
||||||
* returns it to zone. Note, if this is a nonfreeable zone, the memory is
|
* 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.
|
* not actually freed, but the count of number of free()s is updated.<br />
|
||||||
|
* If Garbage Collection is enabled, the zone argument is ignored and this
|
||||||
|
* function causes ptr to be deallocated immediately.
|
||||||
*/
|
*/
|
||||||
GS_EXPORT void
|
GS_EXPORT void
|
||||||
NSZoneFree (NSZone *zone, void *ptr);
|
NSZoneFree (NSZone *zone, void *ptr);
|
||||||
|
@ -165,7 +173,7 @@ GS_EXPORT void
|
||||||
NSSetZoneName (NSZone *zone, NSString *name);
|
NSSetZoneName (NSZone *zone, NSString *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets name of the given zone (useful for debugging and logging).
|
* Returns the name of the given zone (useful for debugging and logging).
|
||||||
*/
|
*/
|
||||||
GS_EXPORT NSString*
|
GS_EXPORT NSString*
|
||||||
NSZoneName (NSZone *zone);
|
NSZoneName (NSZone *zone);
|
||||||
|
|
|
@ -501,7 +501,7 @@ GSPrivateUnloadModule(FILE *errorStream,
|
||||||
void (*unloadCallback)(Class, struct objc_category *)) GS_ATTRIB_PRIVATE;
|
void (*unloadCallback)(Class, struct objc_category *)) GS_ATTRIB_PRIVATE;
|
||||||
|
|
||||||
|
|
||||||
/* Memory to use to put executabel code in.
|
/* Memory to use to put executable code in.
|
||||||
*/
|
*/
|
||||||
@interface GSCodeBuffer : NSObject
|
@interface GSCodeBuffer : NSObject
|
||||||
{
|
{
|
||||||
|
@ -514,6 +514,15 @@ GSPrivateUnloadModule(FILE *errorStream,
|
||||||
- (void) protect;
|
- (void) protect;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
/* Function to safely change the class of an object by 'isa' swizzling
|
||||||
|
* wile maintaining allocation accounting and finalization in a GC world.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GSPrivateSwizzle(id o, Class c) GS_ATTRIB_PRIVATE;
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GSPrivateIsCollectable(const void *ptr) GS_ATTRIB_PRIVATE;
|
||||||
|
|
||||||
NSZone*
|
NSZone*
|
||||||
GSAtomicMallocZone (void);
|
GSAtomicMallocZone (void);
|
||||||
|
|
||||||
|
|
|
@ -592,8 +592,26 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (encoding == internalEncoding)
|
if (encoding == internalEncoding)
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC
|
||||||
|
/* If we are using GC, copy and free any non-collectable buffer so
|
||||||
|
* we don't leak memory.
|
||||||
|
*/
|
||||||
|
if (GSPrivateIsCollectable(chars.c) == NO)
|
||||||
|
{
|
||||||
|
me = (GSStr)NSAllocateObject(GSCInlineStringClass, length,
|
||||||
|
GSObjCZone(self));
|
||||||
|
me->_contents.c = (unsigned char*)&((GSCInlineString*)me)[1];
|
||||||
|
me->_count = length;
|
||||||
|
me->_flags.wide = 0;
|
||||||
|
me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer
|
||||||
|
memcpy(me->_contents.c, chars.c, length);
|
||||||
|
NSZoneFree(NSZoneFromPointer(chars.c), chars.c);
|
||||||
|
return (id)me;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
me = (GSStr)NSAllocateObject(GSCBufferStringClass, 0, GSObjCZone(self));
|
me = (GSStr)NSAllocateObject(GSCBufferStringClass, 0, GSObjCZone(self));
|
||||||
me->_contents.c = chars.c;
|
me->_contents.c = chars.c;
|
||||||
me->_count = length;
|
me->_count = length;
|
||||||
|
@ -658,6 +676,23 @@ fixBOM(unsigned char **bytes, NSUInteger*length, BOOL *owned,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC
|
||||||
|
/* If we are using GC, copy and free any non-collectable buffer so
|
||||||
|
* we don't leak memory.
|
||||||
|
*/
|
||||||
|
if (GSPrivateIsCollectable(chars.u) == NO)
|
||||||
|
{
|
||||||
|
me = (GSStr)NSAllocateObject(GSUnicodeInlineStringClass, length,
|
||||||
|
GSObjCZone(self));
|
||||||
|
me->_contents.u = (unichar*)&((GSUnicodeInlineString*)me)[1];
|
||||||
|
me->_count = length;
|
||||||
|
me->_flags.wide = 1;
|
||||||
|
me->_flags.owned = 1; // Ignored on dealloc, but means we own buffer
|
||||||
|
memcpy(me->_contents.u, chars.u, length * sizeof(unichar));
|
||||||
|
NSZoneFree(NSZoneFromPointer(chars.u), chars.u);
|
||||||
|
return (id)me;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
me = (GSStr)NSAllocateObject(GSUnicodeBufferStringClass,
|
me = (GSStr)NSAllocateObject(GSUnicodeBufferStringClass,
|
||||||
0, GSObjCZone(self));
|
0, GSObjCZone(self));
|
||||||
me->_contents.u = chars.u;
|
me->_contents.u = chars.u;
|
||||||
|
|
|
@ -51,9 +51,11 @@
|
||||||
* NSDataMalloc Concrete class.
|
* NSDataMalloc Concrete class.
|
||||||
* NSDataMappedFile Memory mapped files.
|
* NSDataMappedFile Memory mapped files.
|
||||||
* NSDataShared Extension for shared memory.
|
* NSDataShared Extension for shared memory.
|
||||||
|
* NSDataFinalized For GC of non-GC data.
|
||||||
* NSMutableData Abstract base class.
|
* NSMutableData Abstract base class.
|
||||||
* NSMutableDataMalloc Concrete class.
|
* NSMutableDataMalloc Concrete class.
|
||||||
* NSMutableDataShared Extension for shared memory.
|
* NSMutableDataShared Extension for shared memory.
|
||||||
|
* NSDataMutableFinalized For GC of non-GC data.
|
||||||
*
|
*
|
||||||
* NSMutableDataMalloc MUST share it's initial instance variable layout
|
* NSMutableDataMalloc MUST share it's initial instance variable layout
|
||||||
* with NSDataMalloc so that it can use the 'behavior' code to inherit
|
* with NSDataMalloc so that it can use the 'behavior' code to inherit
|
||||||
|
@ -113,17 +115,20 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@class NSDataMalloc;
|
@class NSDataMalloc;
|
||||||
|
@class NSDataFinalized;
|
||||||
@class NSDataStatic;
|
@class NSDataStatic;
|
||||||
@class NSMutableDataMalloc;
|
@class NSMutableDataMalloc;
|
||||||
|
@class NSMutableDataFinalized;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some static variables to cache classes and methods for quick access -
|
* Some static variables to cache classes and methods for quick access -
|
||||||
* these are set up at process startup or in [NSData +initialize]
|
* these are set up at process startup or in [NSData +initialize]
|
||||||
*/
|
*/
|
||||||
static SEL appendSel;
|
|
||||||
static Class dataStatic;
|
static Class dataStatic;
|
||||||
static Class dataMalloc;
|
static Class dataMalloc;
|
||||||
|
static Class dataFinalized;
|
||||||
static Class mutableDataMalloc;
|
static Class mutableDataMalloc;
|
||||||
|
static Class mutableDataFinalized;
|
||||||
static Class NSDataAbstract;
|
static Class NSDataAbstract;
|
||||||
static Class NSMutableDataAbstract;
|
static Class NSMutableDataAbstract;
|
||||||
static SEL appendSel;
|
static SEL appendSel;
|
||||||
|
@ -294,19 +299,23 @@ failure:
|
||||||
void *bytes;
|
void *bytes;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface NSDataEmpty: NSDataStatic
|
@interface NSDataEmpty: NSDataStatic
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface NSDataMalloc : NSDataStatic
|
@interface NSDataMalloc : NSDataStatic
|
||||||
{
|
@end
|
||||||
}
|
|
||||||
|
@interface NSDataFinalized : NSDataMalloc
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface NSMutableDataMalloc : NSMutableData
|
@interface NSMutableDataMalloc : NSMutableData
|
||||||
{
|
{
|
||||||
NSUInteger length;
|
NSUInteger length;
|
||||||
void *bytes;
|
void *bytes;
|
||||||
#if !GS_WITH_GC
|
#if GS_WITH_GC
|
||||||
|
BOOL owned;
|
||||||
|
#else
|
||||||
NSZone *zone;
|
NSZone *zone;
|
||||||
#endif
|
#endif
|
||||||
NSUInteger capacity;
|
NSUInteger capacity;
|
||||||
|
@ -316,6 +325,9 @@ failure:
|
||||||
- (void) _grow: (NSUInteger)minimum;
|
- (void) _grow: (NSUInteger)minimum;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@interface NSMutableDataFinalized : NSMutableDataMalloc
|
||||||
|
@end
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
@interface NSDataMappedFile : NSDataMalloc
|
@interface NSDataMappedFile : NSDataMalloc
|
||||||
@end
|
@end
|
||||||
|
@ -357,9 +369,11 @@ failure:
|
||||||
{
|
{
|
||||||
NSDataAbstract = self;
|
NSDataAbstract = self;
|
||||||
NSMutableDataAbstract = [NSMutableData class];
|
NSMutableDataAbstract = [NSMutableData class];
|
||||||
dataMalloc = [NSDataMalloc class];
|
|
||||||
dataStatic = [NSDataStatic class];
|
dataStatic = [NSDataStatic class];
|
||||||
|
dataMalloc = [NSDataMalloc class];
|
||||||
|
dataFinalized = [NSDataFinalized class];
|
||||||
mutableDataMalloc = [NSMutableDataMalloc class];
|
mutableDataMalloc = [NSMutableDataMalloc class];
|
||||||
|
mutableDataFinalized = [NSMutableDataFinalized class];
|
||||||
appendSel = @selector(appendBytes:length:);
|
appendSel = @selector(appendBytes:length:);
|
||||||
appendImp = [mutableDataMalloc instanceMethodForSelector: appendSel];
|
appendImp = [mutableDataMalloc instanceMethodForSelector: appendSel];
|
||||||
}
|
}
|
||||||
|
@ -386,7 +400,7 @@ failure:
|
||||||
|
|
||||||
if (empty == nil)
|
if (empty == nil)
|
||||||
{
|
{
|
||||||
empty = [NSDataEmpty allocWithZone: NSDefaultMallocZone()];
|
empty = [dataStatic allocWithZone: NSDefaultMallocZone()];
|
||||||
empty = [empty initWithBytesNoCopy: 0 length: 0 freeWhenDone: NO];
|
empty = [empty initWithBytesNoCopy: 0 length: 0 freeWhenDone: NO];
|
||||||
}
|
}
|
||||||
return empty;
|
return empty;
|
||||||
|
@ -2924,20 +2938,29 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
{
|
{
|
||||||
if (shouldFree == NO)
|
if (shouldFree == NO)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
GSPrivateSwizzle(self, dataStatic);
|
||||||
GSDebugAllocationRemove(self->isa, self);
|
|
||||||
#endif
|
|
||||||
self->isa = dataStatic;
|
|
||||||
#ifndef NDEBUG
|
|
||||||
GSDebugAllocationAdd(self->isa, self);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#if GS_WITH_GC
|
||||||
|
else if (aBuffer != 0 && GSPrivateIsCollectable(aBuffer) == NO)
|
||||||
|
{
|
||||||
|
GSPrivateSwizzle(self, dataFinalized);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
bytes = aBuffer;
|
bytes = aBuffer;
|
||||||
length = bufferSize;
|
length = bufferSize;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation NSDataFinalized
|
||||||
|
- (void) finalize
|
||||||
|
{
|
||||||
|
NSZoneFree(NSDefaultMallocZone(), bytes);
|
||||||
|
[super finalize];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
||||||
@implementation NSDataMappedFile
|
@implementation NSDataMappedFile
|
||||||
|
@ -2947,13 +2970,19 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[self finalize];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) finalize
|
||||||
{
|
{
|
||||||
if (bytes != 0)
|
if (bytes != 0)
|
||||||
{
|
{
|
||||||
munmap(bytes, length);
|
munmap(bytes, length);
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
}
|
}
|
||||||
[super dealloc];
|
[super finalize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3196,10 +3225,18 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
#if GS_WITH_GC
|
||||||
|
if (shouldFree == YES && GSPrivateIsCollectable(aBuffer) == NO)
|
||||||
|
{
|
||||||
|
GSPrivateSwizzle(self, mutableDataFinalized);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
self = [self initWithCapacity: 0];
|
self = [self initWithCapacity: 0];
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
#if !GS_WITH_GC
|
#if GS_WITH_GC
|
||||||
|
owned = shouldFree; // Free memory on finalisation.
|
||||||
|
#else
|
||||||
if (shouldFree == NO)
|
if (shouldFree == NO)
|
||||||
{
|
{
|
||||||
zone = 0; // Don't free this memory.
|
zone = 0; // Don't free this memory.
|
||||||
|
@ -3655,7 +3692,13 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
if (bytes)
|
if (bytes)
|
||||||
{
|
{
|
||||||
memcpy(tmp, bytes, capacity < size ? capacity : size);
|
memcpy(tmp, bytes, capacity < size ? capacity : size);
|
||||||
#if !GS_WITH_GC
|
#if GS_WITH_GC
|
||||||
|
if (owned == YES)
|
||||||
|
{
|
||||||
|
NSZoneFree(NSDefaultMallocZone(), bytes);
|
||||||
|
owned = NO;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (zone == 0)
|
if (zone == 0)
|
||||||
{
|
{
|
||||||
zone = NSDefaultMallocZone();
|
zone = NSDefaultMallocZone();
|
||||||
|
@ -3705,6 +3748,15 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@implementation NSMutableDataFinalized
|
||||||
|
- (void) finalize
|
||||||
|
{
|
||||||
|
if (owned == YES)
|
||||||
|
NSZoneFree(NSDefaultMallocZone(), bytes);
|
||||||
|
[super finalize];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_SHMCTL
|
#ifdef HAVE_SHMCTL
|
||||||
@implementation NSMutableDataShared
|
@implementation NSMutableDataShared
|
||||||
|
@ -3714,6 +3766,12 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) dealloc
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[self finalize];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) finalize
|
||||||
{
|
{
|
||||||
if (bytes != 0)
|
if (bytes != 0)
|
||||||
{
|
{
|
||||||
|
@ -3742,7 +3800,7 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
||||||
capacity = 0;
|
capacity = 0;
|
||||||
shmid = -1;
|
shmid = -1;
|
||||||
}
|
}
|
||||||
[super dealloc];
|
[super finalize];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithBytes: (const void*)aBuffer length: (NSUInteger)bufferSize
|
- (id) initWithBytes: (const void*)aBuffer length: (NSUInteger)bufferSize
|
||||||
|
|
|
@ -484,6 +484,13 @@ NSIncrementExtraRefCount(id anObject)
|
||||||
#endif /* GS_WITH_GC */
|
#endif /* GS_WITH_GC */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define AADD(c, o) GSDebugAllocationAdd(c, o)
|
||||||
|
#define AREM(c, o) GSDebugAllocationRemove(c, o)
|
||||||
|
#else
|
||||||
|
#define AADD(c, o)
|
||||||
|
#define AREM(c, o)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now do conditional compilation of memory allocation functions
|
* Now do conditional compilation of memory allocation functions
|
||||||
|
@ -504,12 +511,49 @@ static void
|
||||||
GSFinalize(void* object, void* data)
|
GSFinalize(void* object, void* data)
|
||||||
{
|
{
|
||||||
[(id)object finalize];
|
[(id)object finalize];
|
||||||
#ifndef NDEBUG
|
AREM(((id)object)->class_pointer, (id)object);
|
||||||
GSDebugAllocationRemove(((id)object)->class_pointer, (id)object);
|
|
||||||
#endif
|
|
||||||
((id)object)->class_pointer = (void*)0xdeadface;
|
((id)object)->class_pointer = (void*)0xdeadface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL
|
||||||
|
GSIsFinalizable(Class c)
|
||||||
|
{
|
||||||
|
if (get_imp(c, finalize_sel) != finalize_imp)
|
||||||
|
return YES;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GSPrivateSwizzle(id o, Class c)
|
||||||
|
{
|
||||||
|
if (o->class_pointer != c)
|
||||||
|
{
|
||||||
|
#if GS_WITH_GC
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
if (GSIsFinalizable(o->class_pointer))
|
||||||
|
{
|
||||||
|
/* Already finalizable, so we just need to do any allocation
|
||||||
|
* accounting.
|
||||||
|
*/
|
||||||
|
AREM(o->class_pointer, o);
|
||||||
|
AADD(c, o);
|
||||||
|
}
|
||||||
|
else if (GSIsFinalizable(c))
|
||||||
|
{
|
||||||
|
/* New clas is finalizable, so we must register the instance
|
||||||
|
* for finalisation and do allocation acounting for it.
|
||||||
|
*/
|
||||||
|
AADD(c, o);
|
||||||
|
GC_REGISTER_FINALIZER (o, GSFinalize, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
#endif /* GS_WITH_GC */
|
||||||
|
o->class_pointer = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline NSObject *
|
inline NSObject *
|
||||||
NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone)
|
NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone)
|
||||||
{
|
{
|
||||||
|
@ -542,16 +586,13 @@ NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone)
|
||||||
if (new != nil)
|
if (new != nil)
|
||||||
{
|
{
|
||||||
new->class_pointer = aClass;
|
new->class_pointer = aClass;
|
||||||
if (get_imp(aClass, finalize_sel) != finalize_imp)
|
if (GSIsFinalizable(aClass))
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
/* We only do allocation counting for objects that can be
|
||||||
/*
|
* finalised - for other objects we have no way of decrementing
|
||||||
* We only do allocation counting for objects that can be
|
* the count when the object is collected.
|
||||||
* finalised - for other objects we have no way of decrementing
|
|
||||||
* the count when the object is collected.
|
|
||||||
*/
|
*/
|
||||||
GSDebugAllocationAdd(aClass, new);
|
AADD(aClass, new);
|
||||||
#endif
|
|
||||||
GC_REGISTER_FINALIZER (new, GSFinalize, NULL, NULL, NULL);
|
GC_REGISTER_FINALIZER (new, GSFinalize, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,9 +617,6 @@ GSObjCZone(NSObject *object)
|
||||||
inline NSObject *
|
inline NSObject *
|
||||||
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
|
NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
|
||||||
extern void GSDebugAllocationAdd(Class c, id o);
|
|
||||||
#endif
|
|
||||||
id new;
|
id new;
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
|
@ -595,9 +633,7 @@ NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
|
||||||
((obj)new)->zone = zone;
|
((obj)new)->zone = zone;
|
||||||
new = (id)&((obj)new)[1];
|
new = (id)&((obj)new)[1];
|
||||||
new->class_pointer = aClass;
|
new->class_pointer = aClass;
|
||||||
#ifndef NDEBUG
|
AADD(aClass, new);
|
||||||
GSDebugAllocationAdd(aClass, new);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
@ -605,17 +641,12 @@ NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone)
|
||||||
inline void
|
inline void
|
||||||
NSDeallocateObject(NSObject *anObject)
|
NSDeallocateObject(NSObject *anObject)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
|
||||||
extern void GSDebugAllocationRemove(Class c, id o);
|
|
||||||
#endif
|
|
||||||
if ((anObject!=nil) && CLS_ISCLASS(((id)anObject)->class_pointer))
|
if ((anObject!=nil) && CLS_ISCLASS(((id)anObject)->class_pointer))
|
||||||
{
|
{
|
||||||
obj o = &((obj)anObject)[-1];
|
obj o = &((obj)anObject)[-1];
|
||||||
NSZone *z = GSObjCZone(anObject);
|
NSZone *z = GSObjCZone(anObject);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
AREM(((id)anObject)->class_pointer, (id)anObject);
|
||||||
GSDebugAllocationRemove(((id)anObject)->class_pointer, (id)anObject);
|
|
||||||
#endif
|
|
||||||
if (NSZombieEnabled == YES)
|
if (NSZombieEnabled == YES)
|
||||||
{
|
{
|
||||||
GSMakeZombie(anObject);
|
GSMakeZombie(anObject);
|
||||||
|
|
|
@ -95,6 +95,20 @@
|
||||||
#include "Foundation/NSString.h"
|
#include "Foundation/NSString.h"
|
||||||
#include "Foundation/NSZone.h"
|
#include "Foundation/NSZone.h"
|
||||||
#include "Foundation/NSLock.h"
|
#include "Foundation/NSLock.h"
|
||||||
|
#include "GSPrivate.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to get more memory - the normal process has failed.
|
||||||
|
* If we can't do anything, just return a null pointer.
|
||||||
|
* Try to do some logging if possible.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
GSOutOfMemory(NSUInteger size, BOOL retry)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "GSOutOfMemory ... wanting %lu bytes.\n",
|
||||||
|
(unsigned long)size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Default zone functions for default zone. */
|
/* Default zone functions for default zone. */
|
||||||
static void* default_malloc (NSZone *zone, size_t size);
|
static void* default_malloc (NSZone *zone, size_t size);
|
||||||
|
@ -196,9 +210,6 @@ NSZone *__nszone_private_hidden_default_zone = &default_zone;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets name of the given zone (useful for debugging and logging).
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
NSSetZoneName (NSZone *zone, NSString *name)
|
NSSetZoneName (NSZone *zone, NSString *name)
|
||||||
{
|
{
|
||||||
|
@ -452,21 +463,15 @@ NSZoneFree (NSZone *zone, void *ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* GS_WITH_GC */
|
BOOL
|
||||||
|
GSPrivateIsCollectable(const void *ptr)
|
||||||
/**
|
|
||||||
* Try to get more memory - the normal process has failed.
|
|
||||||
* If we can't do anything, just return a null pointer.
|
|
||||||
* Try to do some logging if possible.
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
GSOutOfMemory(NSUInteger size, BOOL retry)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "GSOutOfMemory ... wanting %lu bytes.\n",
|
if (GC_base((void*)ptr) == 0) return NO;
|
||||||
(unsigned long)size);
|
else return YES;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* GS_WITH_GC */
|
||||||
|
|
||||||
|
|
||||||
/* Alignment */
|
/* Alignment */
|
||||||
#ifdef ALIGN
|
#ifdef ALIGN
|
||||||
|
@ -1818,10 +1823,6 @@ rrealloc (NSZone *zone, void *ptr, size_t size)
|
||||||
|
|
||||||
static void rnfree (NSZone *zone, void *ptr);
|
static void rnfree (NSZone *zone, void *ptr);
|
||||||
|
|
||||||
/**
|
|
||||||
* Searches and finds the zone ptr was allocated from. The speed depends
|
|
||||||
* upon the number of zones and their size.
|
|
||||||
*/
|
|
||||||
GS_DECLARE NSZone*
|
GS_DECLARE NSZone*
|
||||||
NSZoneFromPointer(void *ptr)
|
NSZoneFromPointer(void *ptr)
|
||||||
{
|
{
|
||||||
|
@ -1845,14 +1846,6 @@ NSZoneFromPointer(void *ptr)
|
||||||
return (zone == 0) ? &default_zone : zone;
|
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
|
|
||||||
* never freed, meaning allocation will be very fast. The whole zone can
|
|
||||||
* still be freed with NSRecycleZone(), and you should still call NSZoneFree
|
|
||||||
* on memory in the zone that is no longer needed, since a count of allocated
|
|
||||||
* pointers is kept and must reach zero before freeing the zone.
|
|
||||||
*/
|
|
||||||
NSZone*
|
NSZone*
|
||||||
NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
|
NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
|
||||||
{
|
{
|
||||||
|
@ -1968,12 +1961,6 @@ NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
|
||||||
return newZone;
|
return newZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
void*
|
void*
|
||||||
NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes)
|
NSZoneCalloc (NSZone *zone, NSUInteger elems, NSUInteger bytes)
|
||||||
{
|
{
|
||||||
|
@ -2069,4 +2056,10 @@ NSZoneStats (NSZone *zone)
|
||||||
return (zone->stats)(zone);
|
return (zone->stats)(zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
GSPrivateIsCollectable(const void *ptr)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* GS_WITH_GC */
|
#endif /* GS_WITH_GC */
|
||||||
|
|
|
@ -90,7 +90,11 @@ callframe_from_info (NSArgumentInfo *info, int numargs, void **retval)
|
||||||
}
|
}
|
||||||
pos = full;
|
pos = full;
|
||||||
full += MAX(info[0].size, sizeof(smallret_t));
|
full += MAX(info[0].size, sizeof(smallret_t));
|
||||||
|
#if GS_WITH_GC
|
||||||
|
cframe = buf = NSAllocateCollectable(full, NSScannedOption);
|
||||||
|
#else
|
||||||
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), full, 1);
|
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), full, 1);
|
||||||
|
#endif
|
||||||
if (cframe)
|
if (cframe)
|
||||||
{
|
{
|
||||||
*retval = buf + pos;
|
*retval = buf + pos;
|
||||||
|
@ -98,7 +102,11 @@ callframe_from_info (NSArgumentInfo *info, int numargs, void **retval)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC
|
||||||
|
cframe = buf = NSAllocateCollectable(size, NSScannedOption);
|
||||||
|
#else
|
||||||
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1);
|
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cframe)
|
if (cframe)
|
||||||
|
@ -567,8 +575,9 @@ callframe_do_call (DOContext *ctxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if !GS_WITH_GC
|
||||||
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
||||||
|
#endif
|
||||||
ctxt->datToFree = 0;
|
ctxt->datToFree = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -647,12 +656,17 @@ callframe_build_return (NSInvocation *inv,
|
||||||
tmptype++;
|
tmptype++;
|
||||||
retLength = objc_sizeof_type(tmptype);
|
retLength = objc_sizeof_type(tmptype);
|
||||||
/* Allocate memory to hold the value we're pointing to. */
|
/* Allocate memory to hold the value we're pointing to. */
|
||||||
|
#if GS_WITH_GC
|
||||||
|
*(void**)retval =
|
||||||
|
NSAllocateCollectable(retLength, NSScannedOption);
|
||||||
|
#else
|
||||||
*(void**)retval =
|
*(void**)retval =
|
||||||
NSZoneCalloc(NSDefaultMallocZone(), retLength, 1);
|
NSZoneCalloc(NSDefaultMallocZone(), retLength, 1);
|
||||||
/* We are responsible for making sure this memory gets free'd
|
/* We are responsible for making sure this memory gets free'd
|
||||||
eventually. Ask NSData class to autorelease it. */
|
eventually. Ask NSData class to autorelease it. */
|
||||||
[NSData dataWithBytesNoCopy: *(void**)retval
|
[NSData dataWithBytesNoCopy: *(void**)retval
|
||||||
length: retLength];
|
length: retLength];
|
||||||
|
#endif
|
||||||
ctxt->type = tmptype;
|
ctxt->type = tmptype;
|
||||||
ctxt->datum = *(void**)retval;
|
ctxt->datum = *(void**)retval;
|
||||||
/* Decode the return value into the memory we allocated. */
|
/* Decode the return value into the memory we allocated. */
|
||||||
|
@ -758,7 +772,9 @@ callframe_build_return (NSInvocation *inv,
|
||||||
|
|
||||||
if (ctxt->datToFree != 0)
|
if (ctxt->datToFree != 0)
|
||||||
{
|
{
|
||||||
|
#if !GS_WITH_GC
|
||||||
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
||||||
|
#endif
|
||||||
ctxt->datToFree = 0;
|
ctxt->datToFree = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,11 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval)
|
||||||
* memory by the ffi stuff.
|
* memory by the ffi stuff.
|
||||||
*/
|
*/
|
||||||
full += 64;
|
full += 64;
|
||||||
|
#if GS_WITH_GC
|
||||||
|
cframe = buf = NSAllocateCollectable(full, NSScannedOption);
|
||||||
|
#else
|
||||||
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), full, 1);
|
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), full, 1);
|
||||||
|
#endif
|
||||||
if (cframe && retval)
|
if (cframe && retval)
|
||||||
{
|
{
|
||||||
*retval = buf + pos;
|
*retval = buf + pos;
|
||||||
|
@ -208,7 +212,11 @@ cifframe_from_info (NSArgumentInfo *info, int numargs, void **retval)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
#if GS_WITH_GC
|
||||||
|
cframe = buf = NSAllocateCollectable(size, NSScannedOption);
|
||||||
|
#else
|
||||||
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1);
|
cframe = buf = NSZoneCalloc(NSDefaultMallocZone(), size, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cframe)
|
if (cframe)
|
||||||
|
@ -1042,8 +1050,9 @@ cifframe_do_call (DOContext *ctxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if !GS_WITH_GC
|
||||||
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
||||||
|
#endif
|
||||||
ctxt->datToFree = 0;
|
ctxt->datToFree = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -1122,12 +1131,17 @@ cifframe_build_return (NSInvocation *inv,
|
||||||
tmptype++;
|
tmptype++;
|
||||||
retLength = objc_sizeof_type(tmptype);
|
retLength = objc_sizeof_type(tmptype);
|
||||||
/* Allocate memory to hold the value we're pointing to. */
|
/* Allocate memory to hold the value we're pointing to. */
|
||||||
|
#if GS_WITH_GC
|
||||||
|
*(void**)retval =
|
||||||
|
NSAllocateCollectable(retLength, NSScannedOption);
|
||||||
|
#else
|
||||||
*(void**)retval =
|
*(void**)retval =
|
||||||
NSZoneCalloc(NSDefaultMallocZone(), retLength, 1);
|
NSZoneCalloc(NSDefaultMallocZone(), retLength, 1);
|
||||||
/* We are responsible for making sure this memory gets free'd
|
/* We are responsible for making sure this memory gets free'd
|
||||||
eventually. Ask NSData class to autorelease it. */
|
eventually. Ask NSData class to autorelease it. */
|
||||||
[NSData dataWithBytesNoCopy: *(void**)retval
|
[NSData dataWithBytesNoCopy: *(void**)retval
|
||||||
length: retLength];
|
length: retLength];
|
||||||
|
#endif
|
||||||
ctxt->type = tmptype;
|
ctxt->type = tmptype;
|
||||||
ctxt->datum = *(void**)retval;
|
ctxt->datum = *(void**)retval;
|
||||||
/* Decode the return value into the memory we allocated. */
|
/* Decode the return value into the memory we allocated. */
|
||||||
|
@ -1232,7 +1246,9 @@ cifframe_build_return (NSInvocation *inv,
|
||||||
|
|
||||||
if (ctxt->datToFree != 0)
|
if (ctxt->datToFree != 0)
|
||||||
{
|
{
|
||||||
|
#if !GS_WITH_GC
|
||||||
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
NSZoneFree(NSDefaultMallocZone(), ctxt->datToFree);
|
||||||
|
#endif
|
||||||
ctxt->datToFree = 0;
|
ctxt->datToFree = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue