diff --git a/GCKit/malloc.m b/GCKit/malloc.m index 06e40d0..832cad0 100644 --- a/GCKit/malloc.m +++ b/GCKit/malloc.m @@ -92,8 +92,7 @@ void *GCAllocateBufferWithZone(void *zone, size_t size, BOOL scan) char *buffer = ((char*)region) + headerSize(gc_buffer_header); if (scan) { - // FIXME: Implement - //GCTraceRegion(region); + GCAddBufferForTracing(region); } // Reference count is 0, so set visited to prevent it from being collected // immediately diff --git a/GCKit/test.m b/GCKit/test.m index e50b67a..deb02b0 100644 --- a/GCKit/test.m +++ b/GCKit/test.m @@ -159,6 +159,7 @@ void putObjectInBuffer(void) { buffer = (id*)GCRetain((id)GCAllocateBufferWithZone(NULL, sizeof(id), YES)); buffer[0] = objc_assign_strongCast([SimpleObject new], buffer); + //fprintf(stderr, "Storing pointer %x in traced memory %x\n", (int)buffer[0], (int)buffer); [*buffer log]; GCDrain(YES); GCDrain(YES); @@ -205,10 +206,10 @@ void makeTracedCycle(void) Pair *p = [Pair new]; id *b2 = GCAllocateBufferWithZone(NULL, sizeof(id), YES); fprintf(stderr, "Expected to leak %x and %x\n", (int)b1, (int)b2); - //objc_assign_strongCast((id)b2, b1); - objc_assign_strongCast(p, b1); + objc_assign_strongCast((id)b2, b1); + //objc_assign_strongCast(p, b1); objc_assign_strongCast((id)b1, b2); - p->a = (id)b2; + p->a = GCRetain((id)b2); } void testTracedCycle(void) @@ -219,6 +220,7 @@ void testTracedCycle(void) int main(void) { testTracedCycle(); + /* // Not required on main thread: //GCRegisterThread(); doStuff(); @@ -230,6 +232,7 @@ int main(void) GCDrain(YES); testCycle(); + */ GCDrain(YES); GCDrain(YES); GCDrain(YES); diff --git a/GCKit/trace.h b/GCKit/trace.h index 274199d..2e9fc7e 100644 --- a/GCKit/trace.h +++ b/GCKit/trace.h @@ -14,6 +14,9 @@ void GCRunTracerIfNeeded(BOOL); void GCAddObjectsForTracing(GCThread *thr); void GCTraceStackSynchronous(GCThread *thr); + +void GCAddBufferForTracing(struct gc_buffer_header *buffer); + 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 063b29a..381925f 100644 --- a/GCKit/trace.m +++ b/GCKit/trace.m @@ -15,6 +15,7 @@ #import "cycle.h" #import "malloc.h" #import "static.h" +#import "workqueue.h" /** * Structure storing pointers that are currently being traced. @@ -212,13 +213,13 @@ static int debugTree(GCTracedRegionTreeNode *node) } /* Invalid binary search tree */ - assert(left != NULL || (GCCompareRegions(left->region, node->region) < 0)); - assert(right != NULL || (GCCompareRegions(right->region, node->region) > 0)); + assert(left == NULL || (GCCompareRegions(left->region, node->region) < 0)); + assert(right == NULL || (GCCompareRegions(right->region, node->region) > 0)); int leftHeight = debugTree(left); int rightHeight = debugTree(right); - assert(leftHeight == 0 || rightHeight ==0 || leftHeight == rightHeight); + //assert(leftHeight == 0 || rightHeight ==0 || leftHeight == rightHeight); /* Only count black children */ if (leftHeight != 0 && rightHeight != 0) @@ -283,7 +284,7 @@ static GCTracedRegionTreeNode *tracedRegionInsert( __attribute__((unused)) static void GCTracedRegionInsert(GCTracedRegion region) { - tracedRegionInsert(GCRegionTreeRoot, region); + GCRegionTreeRoot = tracedRegionInsert(GCRegionTreeRoot, region); GCRegionTreeRoot->colour = BLACK; debugTree(GCRegionTreeRoot); } @@ -427,6 +428,7 @@ static void GCTraceRegion(GCTracedRegion region, void *c) // Stop if we've already found references to everything that might be // garbage. id *object = region.start; + fprintf(stderr, "Region starts at %x (%d bytes)\n", (int)object, (int)region.end - (int)region.start); while (object < (id*)region.end) { if (context->foundObjects == traced_objects->table_used) @@ -434,14 +436,16 @@ static void GCTraceRegion(GCTracedRegion region, void *c) return; } GCTracedPointer *foundObject = traced_object_table_get(traced_objects, *object); - if (foundObject->pointer) + if (foundObject && foundObject->pointer) { + //fprintf(stderr, "Found traced heap pointer to %x\n", (int)foundObject->pointer); if(!GCTestFlag(foundObject->pointer, GCFlagVisited)) { context->foundObjects++; GCSetFlag(foundObject->pointer, GCFlagVisited); } } + object++; } } /** @@ -677,6 +681,20 @@ void GCAddObjectsForTracing(GCThread *thr) pthread_rwlock_unlock(&traced_objects_lock); } +static void GCAddBufferForTracingTrampoline(void *b) +{ + struct gc_buffer_header *buffer = b; + GCTracedRegion region = { buffer, (char*)buffer + sizeof(struct gc_buffer_header), + (char*)buffer + sizeof(struct gc_buffer_header) + buffer->size }; + fprintf(stderr, "Buffer has size %d (%d)\n", buffer->size, (int)region.end - (int)region.start); + GCTracedRegionInsert(region); +} + +void GCAddBufferForTracing(struct gc_buffer_header *buffer) +{ + GCPerform(GCAddBufferForTracingTrampoline, buffer); +} + // TODO: memmove_collectable does this for a whole region, but only does the // locking once. id objc_assign_strongCast(id obj, id *ptr)