mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 08:21:25 +00:00
Make NSPointerArray insert the correct read / write barriers in GC mode.
Add some helper functions to NSConcretePointerFunctions.h that make it easier to do this in the other collections that need to support GC. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@33180 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
f2a470d893
commit
f8ea008b1b
2 changed files with 85 additions and 28 deletions
|
@ -24,6 +24,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import "Foundation/NSPointerFunctions.h"
|
#import "Foundation/NSPointerFunctions.h"
|
||||||
|
#if __OBJC_GC__
|
||||||
|
#include <objc/objc-auto.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Declare a structure type to copy pointer functions information
|
/* Declare a structure type to copy pointer functions information
|
||||||
* around easily.
|
* around easily.
|
||||||
|
@ -58,7 +61,6 @@ typedef struct
|
||||||
@public
|
@public
|
||||||
PFInfo _x;
|
PFInfo _x;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
/* Wrapper functions to make use of the pointer functions.
|
/* Wrapper functions to make use of the pointer functions.
|
||||||
|
@ -72,12 +74,68 @@ pointerFunctionsAcquire(PFInfo *PF, void **dst, void *src)
|
||||||
if (PF->acquireFunction != 0)
|
if (PF->acquireFunction != 0)
|
||||||
src = (*PF->acquireFunction)(src, PF->sizeFunction,
|
src = (*PF->acquireFunction)(src, PF->sizeFunction,
|
||||||
PF->options & NSPointerFunctionsCopyIn ? YES : NO);
|
PF->options & NSPointerFunctionsCopyIn ? YES : NO);
|
||||||
|
#if __OBJC_GC__
|
||||||
|
if (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
||||||
|
{
|
||||||
|
objc_assign_weak((id)src, (id*)dst);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objc_assign_strongCast((id)src, (id*)dst);
|
||||||
|
}
|
||||||
|
#else
|
||||||
#if GSWITHGC
|
#if GSWITHGC
|
||||||
if (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
if (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
||||||
GSAssignZeroingWeakPointer(dst, src);
|
GSAssignZeroingWeakPointer(dst, src);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
*dst = src;
|
*dst = src;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the pointer from the specified address, inserting a read barrier if
|
||||||
|
* required.
|
||||||
|
*/
|
||||||
|
static inline void *pointerFunctionsRead(PFInfo *PF, void **addr)
|
||||||
|
{
|
||||||
|
#if __OBJC_GC__
|
||||||
|
if (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
||||||
|
{
|
||||||
|
return objc_read_weak((id*)addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns a pointer, inserting the correct write barrier if required.
|
||||||
|
*/
|
||||||
|
static inline void pointerFunctionsAssign(PFInfo *PF, void **addr, void *value)
|
||||||
|
{
|
||||||
|
#if __OBJC_GC__
|
||||||
|
if (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
||||||
|
{
|
||||||
|
objc_assign_weak(value, (id*)addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objc_assign_strongCast(value, (id*)addr);
|
||||||
|
}
|
||||||
|
#elif GS_WITH_GC
|
||||||
|
if (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
||||||
|
GSAssignZeroingWeakPointer(itemptr, (void*)0);
|
||||||
|
#else
|
||||||
|
*addr = value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves a pointer from location to another.
|
||||||
|
*/
|
||||||
|
static inline void pointerFunctionsMove(PFInfo *PF, void **new, void **old)
|
||||||
|
{
|
||||||
|
pointerFunctionsAssign(PF, new, pointerFunctionsRead(PF, old));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ static Class concreteClass = Nil;
|
||||||
|
|
||||||
for (i = 0; i < _count; i++)
|
for (i = 0; i < _count; i++)
|
||||||
{
|
{
|
||||||
if (_contents[i] != 0)
|
if (pointerFunctionsRead(&_pf, _contents[i]) != 0)
|
||||||
{
|
{
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
|
@ -256,9 +256,10 @@ static Class concreteClass = Nil;
|
||||||
|
|
||||||
for (i = 0; i < _count; i++)
|
for (i = 0; i < _count; i++)
|
||||||
{
|
{
|
||||||
if (_contents[i] != 0)
|
id obj = pointerFunctionsRead(&_pf, _contents[i]);
|
||||||
|
if (obj != 0)
|
||||||
{
|
{
|
||||||
[a addObject: (id)_contents[i]];
|
[a addObject: obj];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [a makeImmutableCopyOnFail: NO];
|
return [a makeImmutableCopyOnFail: NO];
|
||||||
|
@ -267,26 +268,22 @@ static Class concreteClass = Nil;
|
||||||
|
|
||||||
- (void) compact
|
- (void) compact
|
||||||
{
|
{
|
||||||
NSUInteger i = _count;
|
NSUInteger insert = 0;
|
||||||
|
NSUInteger i;
|
||||||
while (i-- > 0)
|
// We can't use memmove here for __weak pointers, because that would omit the
|
||||||
|
// required read barriers. We could use objc_memmoveCollectable() for strong
|
||||||
|
// pointers, but we may as well use the same code path for everything
|
||||||
|
for (i=0 ; i<_count ; i++)
|
||||||
{
|
{
|
||||||
if (_contents[i] == 0)
|
id obj = pointerFunctionsRead(&_pf, &_contents[i]);
|
||||||
{
|
// If this object is not nil, but at least one before it has been, then
|
||||||
NSUInteger j = i;
|
// move it back to the correct location.
|
||||||
|
if (nil != obj && i != insert)
|
||||||
while (j > 0 && _contents[j-1] != 0)
|
{
|
||||||
{
|
pointerFunctionsAssign(&_pf, &_contents[insert++], obj);
|
||||||
j--;
|
}
|
||||||
}
|
|
||||||
if (i < _count - 1)
|
|
||||||
{
|
|
||||||
memmove(_contents + j, _contents + i + 1,
|
|
||||||
(_count - i) * sizeof(void*));
|
|
||||||
}
|
|
||||||
_count = i = j;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_count = insert;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) copyWithZone: (NSZone*)zone
|
- (id) copyWithZone: (NSZone*)zone
|
||||||
|
@ -312,7 +309,8 @@ static Class concreteClass = Nil;
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < _count; i++)
|
for (i = 0; i < _count; i++)
|
||||||
{
|
{
|
||||||
pointerFunctionsAcquire(&_pf, &c->_contents[i], _contents[i]);
|
pointerFunctionsAcquire(&_pf, &c->_contents[i],
|
||||||
|
pointerFunctionsRead(&_pf, _contents[i]));
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -443,7 +441,7 @@ static Class concreteClass = Nil;
|
||||||
[self setCount: _count + 1];
|
[self setCount: _count + 1];
|
||||||
while (i > index)
|
while (i > index)
|
||||||
{
|
{
|
||||||
_contents[i] = _contents[i-1];
|
pointerFunctionsMove(&_pf, _contents+i, _contents + i-1);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
pointerFunctionsAcquire(&_pf, &_contents[index], pointer);
|
pointerFunctionsAcquire(&_pf, &_contents[index], pointer);
|
||||||
|
@ -468,8 +466,9 @@ static Class concreteClass = Nil;
|
||||||
count = [self count];
|
count = [self count];
|
||||||
while (count-- > 0)
|
while (count-- > 0)
|
||||||
{
|
{
|
||||||
if (pointerFunctionsEqual(&_pf, _contents[count],
|
if (pointerFunctionsEqual(&_pf,
|
||||||
[other pointerAtIndex: count]) == NO)
|
pointerFunctionsRead(&_pf, _contents[count]),
|
||||||
|
[other pointerAtIndex: count]) == NO)
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -481,7 +480,7 @@ static Class concreteClass = Nil;
|
||||||
{
|
{
|
||||||
[self _raiseRangeExceptionWithIndex: index from: _cmd];
|
[self _raiseRangeExceptionWithIndex: index from: _cmd];
|
||||||
}
|
}
|
||||||
return _contents[index];
|
return pointerFunctionsRead(&_pf, &_contents[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSPointerFunctions*) pointerFunctions
|
- (NSPointerFunctions*) pointerFunctions
|
||||||
|
@ -501,7 +500,7 @@ static Class concreteClass = Nil;
|
||||||
pointerFunctionsRelinquish(&_pf, &_contents[index]);
|
pointerFunctionsRelinquish(&_pf, &_contents[index]);
|
||||||
while (++index < _count)
|
while (++index < _count)
|
||||||
{
|
{
|
||||||
_contents[index-1] = _contents[index];
|
pointerFunctionsMove(&_pf, &_contents[index-1], &_contents[index]);
|
||||||
}
|
}
|
||||||
[self setCount: _count - 1];
|
[self setCount: _count - 1];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue