From 1f1c5b5b1a4b12c73e4b213e1285709e5d2f9380 Mon Sep 17 00:00:00 2001 From: theraven Date: Wed, 3 Feb 2010 02:12:10 +0000 Subject: [PATCH] Added test for strong-cast assign (assign to traced memory allocated with GCAllocateCollectable()). Fixed bugs that it showed. --- GCKit/malloc.m | 3 +++ GCKit/test.m | 21 +++++++++++++++++++++ GCKit/trace.h | 1 + GCKit/trace.m | 12 ++++++++---- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/GCKit/malloc.m b/GCKit/malloc.m index 407f377..3a2df23 100644 --- a/GCKit/malloc.m +++ b/GCKit/malloc.m @@ -7,6 +7,7 @@ #import "visit.h" #import "workqueue.h" #include +#include @interface GCObject - (void)finalize; @@ -135,6 +136,7 @@ void GCFreeObjectUnsafe(id object) // finalize it. if (!GCTestFlag(object, GCFlagNotObject)) { + fprintf(stderr, "Finalizing object %x\n", (int)(object)); GCVisitChildren(object, releaseObjects, NULL, YES); [object finalize]; region.end += class_getInstanceSize(object->isa); @@ -148,6 +150,7 @@ void GCFreeObjectUnsafe(id object) } if (GCGetWeakRefCount(object) == 0) { + fprintf(stderr, "Freeing object %x\n", (int)(object)); gc_free_with_zone(GCHeaderForObject(object)->zone, object); } } diff --git a/GCKit/test.m b/GCKit/test.m index 2f6644d..08c00a9 100644 --- a/GCKit/test.m +++ b/GCKit/test.m @@ -137,6 +137,24 @@ void doRefCountStuff(void) makeRefCountedObject(); } +static id *buffer; + +void putObjectInBuffer(void) +{ + buffer = GCAllocateBufferWithZone(NULL, sizeof(id), YES); + buffer[0] = objc_assign_strongCast([SimpleObject new], buffer); + [*buffer log]; + GCDrain(YES); + GCDrain(YES); + sleep(1); +} + +void testTracedMemory(void) +{ + putObjectInBuffer(); + GCDrain(YES); +} + int main(void) { // Not required on main thread: @@ -147,4 +165,7 @@ int main(void) doRefCountStuff(); GCDrain(YES); sleep(2); + testTracedMemory(); + buffer[0] = objc_assign_strongCast(nil, buffer); + GCDrain(YES); } diff --git a/GCKit/trace.h b/GCKit/trace.h index a67ff9d..43b6cb6 100644 --- a/GCKit/trace.h +++ b/GCKit/trace.h @@ -15,3 +15,4 @@ void GCTraceStackSynchronous(GCThread *thr); extern volatile int GCGeneration; void GCCollect(); +id objc_assign_strongCast(id obj, id *ptr); diff --git a/GCKit/trace.m b/GCKit/trace.m index cbc06f5..3ac04d6 100644 --- a/GCKit/trace.m +++ b/GCKit/trace.m @@ -541,6 +541,7 @@ void GCRunTracer(void) object->visitClearedGeneration < threadGeneration) { GCFreeObjectUnsafe(object->pointer); + traced_object_remove(traced_objects, object->pointer); } } } @@ -631,10 +632,13 @@ id objc_assign_strongCast(id obj, id *ptr) { // This object is definitely stored somewhere, so mark it as visited // for now. - GCSetFlag(obj, GCFlagVisited); + if (obj) + { + GCSetFlag(obj, GCFlagVisited); + } pthread_rwlock_wrlock(&traced_objects_lock); GCTracedPointer *old = traced_object_table_get(traced_objects, *ptr); - if (old->pointer) + if (old) { // If the value that we are overwriting is a traced pointer and this is // the pointer to it that we are tracking then mark it as not visited. @@ -649,14 +653,14 @@ id objc_assign_strongCast(id obj, id *ptr) } } GCTracedPointer *new = traced_object_table_get(traced_objects, obj); - if (new->pointer) + if (new) { new->heapAddress = ptr; } pthread_rwlock_unlock(&traced_objects_lock); // Tracing semantics do not apply to objects with CF semantics, so skip the // next bits if the CF flag is set. - if (!GCTestFlag(obj, GCFlagCFObject)) + if (obj && !GCTestFlag(obj, GCFlagCFObject)) { // Don't free this just after scanning the stack. GCSetFlag(obj, GCFlagEscaped);