Fix __weak references to blocks.

main
theraven 15 years ago
parent 126aa409cb
commit d61e9b3209

26
arc.m

@ -14,7 +14,8 @@
pthread_key_t ReturnRetained; pthread_key_t ReturnRetained;
#endif #endif
extern struct objc_class _NSConcreteStackBlock; extern void _NSConcreteStackBlock;
extern void _NSConcreteGlobalBlock;
@interface NSAutoreleasePool @interface NSAutoreleasePool
+ (Class)class; + (Class)class;
@ -247,10 +248,15 @@ PRIVATE void init_arc(void)
#endif #endif
} }
void* block_load_weak(void *block);
id objc_storeWeak(id *addr, id obj) id objc_storeWeak(id *addr, id obj)
{ {
fprintf(stderr, "Storing weak value %p\n", obj);
id old = *addr; id old = *addr;
LOCK_FOR_SCOPE(&weakRefLock); LOCK_FOR_SCOPE(&weakRefLock);
if (nil != old)
{
WeakRef *oldRef = weak_ref_table_get(weakRefs, old); WeakRef *oldRef = weak_ref_table_get(weakRefs, old);
while (NULL != oldRef) while (NULL != oldRef)
{ {
@ -264,12 +270,29 @@ id objc_storeWeak(id *addr, id obj)
} }
} }
} }
}
if (nil == obj) if (nil == obj)
{ {
*addr = obj; *addr = obj;
return nil; return nil;
} }
if (&_NSConcreteGlobalBlock == obj->isa)
{
// If this is a global block, it's never deallocated, so secretly make
// this a strong reference
// TODO: We probably also want to do the same for constant strings and
// classes.
*addr = obj;
return obj;
}
if (&_NSConcreteStackBlock == obj->isa)
{
block_load_weak(obj);
}
else
{
obj = _objc_weak_load(obj); obj = _objc_weak_load(obj);
}
if (nil != obj) if (nil != obj)
{ {
WeakRef *ref = weak_ref_table_get(weakRefs, obj); WeakRef *ref = weak_ref_table_get(weakRefs, obj);
@ -301,6 +324,7 @@ id objc_storeWeak(id *addr, id obj)
weak_ref_insert(weakRefs, newRef); weak_ref_insert(weakRefs, newRef);
} }
} }
*addr = obj;
return obj; return obj;
} }

@ -27,6 +27,7 @@
#import "objc/runtime.h" #import "objc/runtime.h"
#import "objc/objc-arc.h" #import "objc/objc-arc.h"
#include "gc_ops.h" #include "gc_ops.h"
#include "visibility.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -496,7 +497,14 @@ void _Block_release(void *src)
{ {
if(self->flags & BLOCK_HAS_COPY_DISPOSE) if(self->flags & BLOCK_HAS_COPY_DISPOSE)
self->descriptor->dispose_helper(self); self->descriptor->dispose_helper(self);
objc_delete_weak_refs((id)self);
gc->free(self); gc->free(self);
} }
} }
} }
PRIVATE void* block_load_weak(void *block)
{
struct block_literal *self = block;
return (self->reserved) > 0 ? block : 0;
}

Loading…
Cancel
Save