diff --git a/Source/NSConcreteHashTable.m b/Source/NSConcreteHashTable.m index 6f6a636e9..258fd20ee 100644 --- a/Source/NSConcreteHashTable.m +++ b/Source/NSConcreteHashTable.m @@ -173,16 +173,16 @@ NSCompareHashTables(NSHashTable *table1, NSHashTable *table2) { BOOL result = YES; NSHashEnumerator enumerator; - GSIMapNode n; + GSIMapNode n1; enumerator = NSEnumerateHashTable(table1); if (GSObjCClass(table2) == concreteClass) { GSIMapTable t2 = (GSIMapTable)table2; - while ((n = GSIMapEnumeratorNextNode(&enumerator)) != 0) + while ((n1 = GSIMapEnumeratorNextNode(&enumerator)) != 0) { - if (GSIMapNodeForKey(t2, n->key) == 0) + if (GSIMapNodeForKey(t2, n1->key) == 0) { result = NO; break; @@ -191,12 +191,13 @@ NSCompareHashTables(NSHashTable *table1, NSHashTable *table2) } else { - while ((n = GSIMapEnumeratorNextNode(&enumerator)) != 0) + while ((n1 = GSIMapEnumeratorNextNode(&enumerator)) != 0) { + void *v1 = n1->key.ptr; void *v2; - v2 = NSHashGet(table2, n->key.ptr); - if (v2 == 0 && v2 != n->key.ptr) + v2 = NSHashGet(table2, v1); + if (v2 == 0 && v2 != v1) { result = NO; break; @@ -215,9 +216,10 @@ NSCompareHashTables(NSHashTable *table1, NSHashTable *table2) enumerator = NSEnumerateHashTable(table1); while ((v1 = NSNextHashEnumeratorItem(&enumerator)) != 0) { - void *v2 = NSHashGet(table2, v1); + void *v2; - if ((v2 = NSHashGet(table2, v1)) == 0) + v2 = NSHashGet(table2, v1); + if (v2 == 0 && v2 != v1) { result = NO; break; @@ -793,29 +795,20 @@ const NSHashTableCallBacks NSPointerToStructHashCallBacks = - (id) initWithPointerFunctions: (NSPointerFunctions*)functions capacity: (NSUInteger)initialCapacity { - if (functions == nil) - { - functions = [NSPointerFunctions pointerFunctionsWithOptions: 0]; - } legacy = NO; - if ([functions class] == [NSConcretePointerFunctions class]) + if (![functions isKindOfClass: [NSConcretePointerFunctions class]]) { - memcpy(&self->cb.pf, &((NSConcretePointerFunctions*)functions)->_x, - sizeof(self->cb.pf)); - } - else - { - self->cb.pf.acquireFunction = [functions acquireFunction]; - self->cb.pf.descriptionFunction = [functions descriptionFunction]; - self->cb.pf.hashFunction = [functions hashFunction]; - self->cb.pf.isEqualFunction = [functions isEqualFunction]; - self->cb.pf.relinquishFunction = [functions relinquishFunction]; - self->cb.pf.sizeFunction = [functions sizeFunction]; - self->cb.pf.usesStrongWriteBarrier - = [functions usesStrongWriteBarrier]; - self->cb.pf.usesWeakReadAndWriteBarriers - = [functions usesWeakReadAndWriteBarriers]; + static NSConcretePointerFunctions *defaultFunctions = nil; + + if (defaultFunctions == nil) + { + defaultFunctions + = [[NSConcretePointerFunctions alloc] initWithOptions: 0]; + } + functions = defaultFunctions; } + memcpy(&self->cb.pf, &((NSConcretePointerFunctions*)functions)->_x, + sizeof(self->cb.pf)); #if GC_WITH_GC if (self->cb.pf.usesWeakReadAndWriteBarriers) @@ -831,11 +824,6 @@ const NSHashTableCallBacks NSPointerToStructHashCallBacks = return self; } -- (BOOL) isEqualToHashTable: (NSHashTable*)other -{ - return NSCompareHashTables(self, other); -} - - (NSEnumerator*) objectEnumerator { return [self subclassResponsibility: _cmd]; diff --git a/Source/NSConcreteMapTable.m b/Source/NSConcreteMapTable.m index 2e626494f..cb2453105 100644 --- a/Source/NSConcreteMapTable.m +++ b/Source/NSConcreteMapTable.m @@ -179,6 +179,13 @@ NSAllMapTableValues(NSMapTable *table) return valueArray; } +static BOOL +equalPointers(const void *item1, const void *item2, + NSUInteger (*size)(const void *item)) +{ + return (item1 == item2) ? YES : NO; +} + /** * Compares the two map tables for equality. * If the tables are different sizes, returns NO. @@ -190,43 +197,123 @@ NSAllMapTableValues(NSMapTable *table) BOOL NSCompareMapTables(NSMapTable *table1, NSMapTable *table2) { - GSIMapTable t1 = (GSIMapTable)table1; - GSIMapTable t2 = (GSIMapTable)table2; - - if (t1 == t2) + if (table1 == table2) { return YES; } - if (t1 == nil) + if (table1 == nil) { NSWarnFLog(@"Null first argument supplied"); return NO; } - if (t2 == nil) + if (table2 == nil) { NSWarnFLog(@"Null second argument supplied"); return NO; } - if (t1->nodeCount != t2->nodeCount) + if ([table1 count] != [table2 count]) { return NO; } + + if (GSObjCClass(table1) != concreteClass + && GSObjCClass(table2) == concreteClass) + { + id t = table1; + + table1 = table2; + table2 = t; + } + + if (GSObjCClass(table1) == concreteClass) + { + NSConcreteMapTable *c1 = (NSConcreteMapTable*)table1; + GSIMapTable t1 = (GSIMapTable)table1; + BOOL result = YES; + NSMapEnumerator enumerator; + GSIMapNode n1; + + enumerator = GSIMapEnumeratorForMap(t1); + if (GSObjCClass(table2) == concreteClass) + { + GSIMapTable t2 = (GSIMapTable)table2; + + while ((n1 = GSIMapEnumeratorNextNode(&enumerator)) != 0) + { + GSIMapNode n2; + + n2 = GSIMapNodeForKey(t2, n1->key); + if (n2 == 0) + { + result = NO; + } + else + { + void *v1 = n1->value.ptr; + void *v2 = n2->value.ptr; + + result = (c1->legacy + ? c1->cb.old.k.isEqual(c1, v1, v2) + : pointerFunctionsEqual(&c1->cb.pf.v, v2, v2)); + } + if (result == NO) + { + break; + } + } + } + else + { + while ((n1 = GSIMapEnumeratorNextNode(&enumerator)) != 0) + { + void *k1 = n1->key.ptr; + void *v1 = n1->value.ptr; + void *v2 = NSMapGet(table2, k1); + + result = (c1->legacy + ? c1->cb.old.k.isEqual(c1, v1, v2) + : pointerFunctionsEqual(&c1->cb.pf.v, v1, v2)); + if (result == NO) + { + break; + } + } + } + GSIMapEndEnumerator((GSIMapEnumerator)&enumerator); + return result; + } else { - NSMapEnumerator enumerator = GSIMapEnumeratorForMap((GSIMapTable)t1); - GSIMapNode n; + BOOL result = YES; + NSMapEnumerator enumerator; + void *k1; + void *v1; + NSPointerFunctions *pf; + BOOL (*isEqualFunction)(const void *item1, const void *item2, + NSUInteger (*size)(const void *item)); + NSUInteger (*sizeFunction)(const void *item); - while ((n = GSIMapEnumeratorNextNode(&enumerator)) != 0) - { - if (GSIMapNodeForKey(t2, n->key) == 0) - { - GSIMapEndEnumerator((GSIMapEnumerator)&enumerator); - return NO; - } - } - GSIMapEndEnumerator((GSIMapEnumerator)&enumerator); - return YES; + /* Get functions needed for comparison. + */ + pf = [table1 valuePointerFunctions]; + isEqualFunction = [pf isEqualFunction]; + sizeFunction = [pf sizeFunction]; + if (isEqualFunction == 0) isEqualFunction = equalPointers; + + enumerator = NSEnumerateMapTable(table1); + while (NSNextMapEnumeratorPair(&enumerator, &k1, &v1) == YES) + { + void *v2 = NSMapGet(table2, k1); + + if ((*isEqualFunction)(v1, v2, sizeFunction) == NO) + { + result = NO; + break; + } + } + NSEndMapTableEnumeration(&enumerator); + return result; } } @@ -915,51 +1002,28 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks = valuePointerFunctions: (NSPointerFunctions*)valueFunctions capacity: (NSUInteger)initialCapacity { - if (keyFunctions == nil) + static NSConcretePointerFunctions *defaultFunctions = nil; + + if (defaultFunctions == nil) { - keyFunctions = [NSPointerFunctions pointerFunctionsWithOptions: 0]; - } - if (valueFunctions == nil) - { - valueFunctions = [NSPointerFunctions pointerFunctionsWithOptions: 0]; + defaultFunctions + = [[NSConcretePointerFunctions alloc] initWithOptions: 0]; } legacy = NO; - if ([keyFunctions class] == [NSConcretePointerFunctions class]) + + if (![keyFunctions isKindOfClass: [NSConcretePointerFunctions class]]) { - memcpy(&self->cb.pf.k, &((NSConcretePointerFunctions*)keyFunctions)->_x, - sizeof(self->cb.pf.k)); + keyFunctions = defaultFunctions; } - else + memcpy(&self->cb.pf.k, &((NSConcretePointerFunctions*)keyFunctions)->_x, + sizeof(self->cb.pf.k)); + + if (![valueFunctions isKindOfClass: [NSConcretePointerFunctions class]]) { - self->cb.pf.k.acquireFunction = [keyFunctions acquireFunction]; - self->cb.pf.k.descriptionFunction = [keyFunctions descriptionFunction]; - self->cb.pf.k.hashFunction = [keyFunctions hashFunction]; - self->cb.pf.k.isEqualFunction = [keyFunctions isEqualFunction]; - self->cb.pf.k.relinquishFunction = [keyFunctions relinquishFunction]; - self->cb.pf.k.sizeFunction = [keyFunctions sizeFunction]; - self->cb.pf.k.usesStrongWriteBarrier - = [keyFunctions usesStrongWriteBarrier]; - self->cb.pf.k.usesWeakReadAndWriteBarriers - = [keyFunctions usesWeakReadAndWriteBarriers]; - } - if ([valueFunctions class] == [NSConcretePointerFunctions class]) - { - memcpy(&self->cb.pf.v, &((NSConcretePointerFunctions*)valueFunctions)->_x, - sizeof(self->cb.pf.v)); - } - else - { - self->cb.pf.v.acquireFunction = [valueFunctions acquireFunction]; - self->cb.pf.v.descriptionFunction = [valueFunctions descriptionFunction]; - self->cb.pf.v.hashFunction = [valueFunctions hashFunction]; - self->cb.pf.v.isEqualFunction = [valueFunctions isEqualFunction]; - self->cb.pf.v.relinquishFunction = [valueFunctions relinquishFunction]; - self->cb.pf.v.sizeFunction = [valueFunctions sizeFunction]; - self->cb.pf.v.usesStrongWriteBarrier - = [valueFunctions usesStrongWriteBarrier]; - self->cb.pf.v.usesWeakReadAndWriteBarriers - = [valueFunctions usesWeakReadAndWriteBarriers]; + valueFunctions = defaultFunctions; } + memcpy(&self->cb.pf.v, &((NSConcretePointerFunctions*)valueFunctions)->_x, + sizeof(self->cb.pf.v)); #if GC_WITH_GC if (self->cb.pf.k.usesWeakReadAndWriteBarriers) @@ -991,7 +1055,7 @@ const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks = - (BOOL) isEqual: (id)other { - return (BOOL)(uintptr_t)[self subclassResponsibility: _cmd]; + return NSCompareMapTables(self, other); } - (NSEnumerator*) keyEnumerator diff --git a/Source/NSConcretePointerFunctions.h b/Source/NSConcretePointerFunctions.h index b44f8a523..01db0ef13 100644 --- a/Source/NSConcretePointerFunctions.h +++ b/Source/NSConcretePointerFunctions.h @@ -46,11 +46,8 @@ typedef struct NSUInteger (*sizeFunction)(const void *item); - BOOL shouldCopyIn; + NSPointerFunctionsOptions options; - BOOL usesStrongWriteBarrier; - - BOOL usesWeakReadAndWriteBarriers; } PFInfo; /* Declare the concrete pointer functions class as a wrapper around @@ -73,9 +70,10 @@ static inline void pointerFunctionsAcquire(PFInfo *PF, void **dst, void *src) { if (PF->acquireFunction != 0) - src = (*PF->acquireFunction)(src, PF->sizeFunction, PF->shouldCopyIn); + src = (*PF->acquireFunction)(src, PF->sizeFunction, + PF->options & NSPointerFunctionsCopyIn ? YES : NO); #if GSWITHGC - if (PF->usesWeakReadAndWriteBarriers) + if (PF->options & NSPointerFunctionsZeroingWeakMemory) GSAssignZeroingWeakPointer(dst, src); else #endif @@ -125,7 +123,7 @@ pointerFunctionsRelinquish(PFInfo *PF, void **itemptr) { if (PF->relinquishFunction != 0) (*PF->relinquishFunction)(*itemptr, PF->sizeFunction); - if (PF->usesWeakReadAndWriteBarriers) + if (PF->options & NSPointerFunctionsZeroingWeakMemory) GSAssignZeroingWeakPointer(itemptr, (void*)0); else *itemptr = 0; @@ -138,11 +136,12 @@ pointerFunctionsReplace(PFInfo *PF, void **dst, void *src) if (src != *dst) { if (PF->acquireFunction != 0) - src = (*PF->acquireFunction)(src, PF->sizeFunction, PF->shouldCopyIn); + src = (*PF->acquireFunction)(src, PF->sizeFunction, + PF->options & NSPointerFunctionsCopyIn ? YES : NO); if (PF->relinquishFunction != 0) (*PF->relinquishFunction)(*dst, PF->sizeFunction); #if GSWITHGC - if (PF->usesWeakReadAndWriteBarriers) + if (PF->options & NSPointerFunctionsZeroingWeakMemory) GSAssignZeroingWeakPointer(dst, src); else #endif diff --git a/Source/NSConcretePointerFunctions.m b/Source/NSConcretePointerFunctions.m index d723916e3..4b42e73bf 100644 --- a/Source/NSConcretePointerFunctions.m +++ b/Source/NSConcretePointerFunctions.m @@ -187,6 +187,8 @@ relinquishRetainedMemory(const void *item, - (id) initWithOptions: (NSPointerFunctionsOptions)options { + _x.options = options; + /* First we look at the memory management options to see which function * should be used to relinquish contents of a container with these * options. @@ -194,7 +196,6 @@ relinquishRetainedMemory(const void *item, if (options & NSPointerFunctionsZeroingWeakMemory) { _x.relinquishFunction = 0; - _x.usesWeakReadAndWriteBarriers = YES; } else if (options & NSPointerFunctionsOpaqueMemory) { @@ -210,19 +211,9 @@ relinquishRetainedMemory(const void *item, } else { - /* Only retained pointers need the array memory to be scanned, - * so for these we set the usesStrongWriteBarrier flag to tell - * containers to allocate scanned memory. - */ - _x.usesStrongWriteBarrier = YES; _x.relinquishFunction = relinquishRetainedMemory; } - if (options & NSPointerFunctionsCopyIn) - { - _x.shouldCopyIn = YES; - } - /* Now we look at the personality options to determine other functions. */ if (options & NSPointerFunctionsOpaquePersonality) @@ -336,12 +327,20 @@ relinquishRetainedMemory(const void *item, - (void) setUsesStrongWriteBarrier: (BOOL)flag { - _x.usesStrongWriteBarrier = flag; + _x.options &= + ~(NSPointerFunctionsZeroingWeakMemory + |NSPointerFunctionsOpaqueMemory + |NSPointerFunctionsMallocMemory + |NSPointerFunctionsMachVirtualMemory); } - (void) setUsesWeakReadAndWriteBarriers: (BOOL)flag { - _x.usesWeakReadAndWriteBarriers = flag; + _x.options |= NSPointerFunctionsZeroingWeakMemory; + _x.options &= + ~(NSPointerFunctionsOpaqueMemory + |NSPointerFunctionsMallocMemory + |NSPointerFunctionsMachVirtualMemory); } - (NSUInteger (*)(const void *item)) sizeFunction @@ -351,12 +350,20 @@ relinquishRetainedMemory(const void *item, - (BOOL) usesStrongWriteBarrier { - return _x.usesStrongWriteBarrier; + if ((_x.options & + (NSPointerFunctionsZeroingWeakMemory + |NSPointerFunctionsOpaqueMemory + |NSPointerFunctionsMallocMemory + |NSPointerFunctionsMachVirtualMemory)) == NSPointerFunctionsStrongMemory) + return YES; + return NO; } - (BOOL) usesWeakReadAndWriteBarriers { - return _x.usesStrongWriteBarrier; + if (_x.options & NSPointerFunctionsZeroingWeakMemory) + return YES; + return NO; } @end diff --git a/Source/NSHashTable.m b/Source/NSHashTable.m index 11eb8b64b..379e6572a 100644 --- a/Source/NSHashTable.m +++ b/Source/NSHashTable.m @@ -160,15 +160,13 @@ static Class concreteClass = 0; - (BOOL) isEqual: (id)other { - if (other == self) return YES; - if (other == nil) return NO; if ([other isKindOfClass: abstractClass] == NO) return NO; - return [self isEqualToHashTable: other]; + return NSCompareHashTables(self, other); } - (BOOL) isEqualToHashTable: (NSHashTable*)other { - return (BOOL)(uintptr_t)[self subclassResponsibility: _cmd]; + return NSCompareHashTables(self, other); } - (BOOL) isSubsetOfHashTable: (NSHashTable*)other diff --git a/Source/NSMapTable.m b/Source/NSMapTable.m index 8f174a248..3f1f55347 100644 --- a/Source/NSMapTable.m +++ b/Source/NSMapTable.m @@ -166,7 +166,8 @@ static Class concreteClass = 0; - (BOOL) isEqual: (id)other { - return (BOOL)(uintptr_t)[self subclassResponsibility: _cmd]; + if ([other isKindOfClass: abstractClass] == NO) return NO; + return NSCompareMapTables(self, other); } - (NSEnumerator*) keyEnumerator diff --git a/Source/NSPointerArray.m b/Source/NSPointerArray.m index 985773815..ba70bb155 100644 --- a/Source/NSPointerArray.m +++ b/Source/NSPointerArray.m @@ -269,7 +269,7 @@ static Class concreteClass = Nil; c->_capacity = c->_count; c->_grow_factor = c->_capacity/2; #if GS_WITH_GC - if (_pf.usesWeakReadAndWriteBarriers) + if (_pf.options & NSPointerFunctionsZeroingWeakMemory) { c->_contents = NSAllocateCollectable(sizeof(id) * _count, 0); } @@ -350,7 +350,7 @@ static Class concreteClass = Nil; if (_count > 0) { #if GS_WITH_GC - if (_pf.usesWeakReadAndWriteBarriers) + if (_pf.options & NSPointerFunctionsZeroingWeakMemory) { _contents = NSAllocateCollectable(sizeof(id) * _count, 0); } @@ -387,23 +387,18 @@ static Class concreteClass = Nil; - (id) initWithPointerFunctions: (NSPointerFunctions*)functions { - if ([functions class] == [NSConcretePointerFunctions class]) + if (![functions isKindOfClass: [NSConcretePointerFunctions class]]) { - memcpy(&_pf, &((NSConcretePointerFunctions*)functions)->_x, sizeof(_pf)); - } - else - { - _pf.acquireFunction = [functions acquireFunction]; - _pf.descriptionFunction = [functions descriptionFunction]; - _pf.hashFunction = [functions hashFunction]; - _pf.isEqualFunction = [functions isEqualFunction]; - _pf.relinquishFunction = [functions relinquishFunction]; - _pf.sizeFunction = [functions sizeFunction]; - _pf.usesStrongWriteBarrier - = [functions usesStrongWriteBarrier]; - _pf.usesWeakReadAndWriteBarriers - = [functions usesWeakReadAndWriteBarriers]; + static NSConcretePointerFunctions *defaultFunctions = nil; + + if (defaultFunctions == nil) + { + defaultFunctions + = [[NSConcretePointerFunctions alloc] initWithOptions: 0]; + } + functions = defaultFunctions; } + memcpy(&_pf, &((NSConcretePointerFunctions*)functions)->_x, sizeof(_pf)); return self; } @@ -516,7 +511,7 @@ static Class concreteClass = Nil; #if GS_WITH_GC ptr = (void**)NSZoneMalloc([self zone], size); #else - if (_pf.usesWeakReadAndWriteBarriers) + if (_pf.options & NSPointerFunctionsZeroingWeakMemory) { ptr = (void**)NSAllocateCollectable(size, 0); } @@ -531,7 +526,7 @@ static Class concreteClass = Nil; #if GS_WITH_GC ptr = (void**)NSZoneRealloc([self zone], _contents, size); #else - if (_pf.usesWeakReadAndWriteBarriers) + if (_pf.options & NSPointerFunctionsZeroingWeakMemory) { ptr = (void**)NSReallocateCollectable( _contents, size, 0);