mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-29 16:01:38 +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
3aa5c524e6
commit
0f262c600e
2 changed files with 85 additions and 28 deletions
|
@ -24,6 +24,9 @@
|
|||
*/
|
||||
|
||||
#import "Foundation/NSPointerFunctions.h"
|
||||
#if __OBJC_GC__
|
||||
#include <objc/objc-auto.h>
|
||||
#endif
|
||||
|
||||
/* Declare a structure type to copy pointer functions information
|
||||
* around easily.
|
||||
|
@ -58,7 +61,6 @@ typedef struct
|
|||
@public
|
||||
PFInfo _x;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/* Wrapper functions to make use of the pointer functions.
|
||||
|
@ -72,12 +74,68 @@ pointerFunctionsAcquire(PFInfo *PF, void **dst, void *src)
|
|||
if (PF->acquireFunction != 0)
|
||||
src = (*PF->acquireFunction)(src, PF->sizeFunction,
|
||||
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 (PF->options & NSPointerFunctionsZeroingWeakMemory)
|
||||
GSAssignZeroingWeakPointer(dst, src);
|
||||
else
|
||||
#endif
|
||||
*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++)
|
||||
{
|
||||
if (_contents[i] != 0)
|
||||
if (pointerFunctionsRead(&_pf, _contents[i]) != 0)
|
||||
{
|
||||
c++;
|
||||
}
|
||||
|
@ -256,9 +256,10 @@ static Class concreteClass = Nil;
|
|||
|
||||
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];
|
||||
|
@ -267,26 +268,22 @@ static Class concreteClass = Nil;
|
|||
|
||||
- (void) compact
|
||||
{
|
||||
NSUInteger i = _count;
|
||||
|
||||
while (i-- > 0)
|
||||
NSUInteger insert = 0;
|
||||
NSUInteger i;
|
||||
// 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)
|
||||
{
|
||||
NSUInteger j = i;
|
||||
|
||||
while (j > 0 && _contents[j-1] != 0)
|
||||
{
|
||||
j--;
|
||||
}
|
||||
if (i < _count - 1)
|
||||
{
|
||||
memmove(_contents + j, _contents + i + 1,
|
||||
(_count - i) * sizeof(void*));
|
||||
}
|
||||
_count = i = j;
|
||||
}
|
||||
id obj = pointerFunctionsRead(&_pf, &_contents[i]);
|
||||
// If this object is not nil, but at least one before it has been, then
|
||||
// move it back to the correct location.
|
||||
if (nil != obj && i != insert)
|
||||
{
|
||||
pointerFunctionsAssign(&_pf, &_contents[insert++], obj);
|
||||
}
|
||||
}
|
||||
_count = insert;
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone*)zone
|
||||
|
@ -312,7 +309,8 @@ static Class concreteClass = Nil;
|
|||
#endif
|
||||
for (i = 0; i < _count; i++)
|
||||
{
|
||||
pointerFunctionsAcquire(&_pf, &c->_contents[i], _contents[i]);
|
||||
pointerFunctionsAcquire(&_pf, &c->_contents[i],
|
||||
pointerFunctionsRead(&_pf, _contents[i]));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
@ -443,7 +441,7 @@ static Class concreteClass = Nil;
|
|||
[self setCount: _count + 1];
|
||||
while (i > index)
|
||||
{
|
||||
_contents[i] = _contents[i-1];
|
||||
pointerFunctionsMove(&_pf, _contents+i, _contents + i-1);
|
||||
i--;
|
||||
}
|
||||
pointerFunctionsAcquire(&_pf, &_contents[index], pointer);
|
||||
|
@ -468,8 +466,9 @@ static Class concreteClass = Nil;
|
|||
count = [self count];
|
||||
while (count-- > 0)
|
||||
{
|
||||
if (pointerFunctionsEqual(&_pf, _contents[count],
|
||||
[other pointerAtIndex: count]) == NO)
|
||||
if (pointerFunctionsEqual(&_pf,
|
||||
pointerFunctionsRead(&_pf, _contents[count]),
|
||||
[other pointerAtIndex: count]) == NO)
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
|
@ -481,7 +480,7 @@ static Class concreteClass = Nil;
|
|||
{
|
||||
[self _raiseRangeExceptionWithIndex: index from: _cmd];
|
||||
}
|
||||
return _contents[index];
|
||||
return pointerFunctionsRead(&_pf, &_contents[index]);
|
||||
}
|
||||
|
||||
- (NSPointerFunctions*) pointerFunctions
|
||||
|
@ -501,7 +500,7 @@ static Class concreteClass = Nil;
|
|||
pointerFunctionsRelinquish(&_pf, &_contents[index]);
|
||||
while (++index < _count)
|
||||
{
|
||||
_contents[index-1] = _contents[index];
|
||||
pointerFunctionsMove(&_pf, &_contents[index-1], &_contents[index]);
|
||||
}
|
||||
[self setCount: _count - 1];
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue