diff --git a/Source/NSConcretePointerFunctions.h b/Source/NSConcretePointerFunctions.h index 01db0ef13..728ac9af4 100644 --- a/Source/NSConcretePointerFunctions.h +++ b/Source/NSConcretePointerFunctions.h @@ -24,6 +24,9 @@ */ #import "Foundation/NSPointerFunctions.h" +#if __OBJC_GC__ +#include +#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)); } diff --git a/Source/NSPointerArray.m b/Source/NSPointerArray.m index b323812b2..9358ee153 100644 --- a/Source/NSPointerArray.m +++ b/Source/NSPointerArray.m @@ -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]; }