Better recovery when things are done in the wrong order.

main
theraven 15 years ago
parent 3754c9fdbe
commit e69ed0696d

54
arc.m

@ -177,6 +177,30 @@ static inline void release(id obj)
[obj release]; [obj release];
} }
static inline void initAutorelease(void)
{
if (Nil == AutoreleasePool)
{
AutoreleasePool = objc_getRequiredClass("NSAutoreleasePool");
if (Nil == AutoreleasePool)
{
useARCAutoreleasePool = YES;
}
else
{
[AutoreleasePool class];
useARCAutoreleasePool = class_respondsToSelector(AutoreleasePool,
SELECTOR(_ARCCompatibleAutoreleasePool));
NewAutoreleasePool = class_getMethodImplementation(object_getClass(AutoreleasePool),
SELECTOR(new));
DeleteAutoreleasePool = class_getMethodImplementation(AutoreleasePool,
SELECTOR(release));
AutoreleaseAdd = class_getMethodImplementation(object_getClass(AutoreleasePool),
SELECTOR(addObject:));
}
}
}
static inline id autorelease(id obj) static inline id autorelease(id obj)
{ {
//fprintf(stderr, "Autoreleasing %p\n", obj); //fprintf(stderr, "Autoreleasing %p\n", obj);
@ -200,7 +224,11 @@ static inline id autorelease(id obj)
} }
if (objc_test_class_flag(obj->isa, objc_class_flag_fast_arc)) if (objc_test_class_flag(obj->isa, objc_class_flag_fast_arc))
{ {
AutoreleaseAdd(AutoreleasePool, SELECTOR(addObject:), obj); initAutorelease();
if (0 != AutoreleaseAdd)
{
AutoreleaseAdd(AutoreleasePool, SELECTOR(addObject:), obj);
}
return obj; return obj;
} }
return [obj autorelease]; return [obj autorelease];
@ -209,26 +237,6 @@ static inline id autorelease(id obj)
void *objc_autoreleasePoolPush(void) void *objc_autoreleasePoolPush(void)
{ {
if (Nil == AutoreleasePool)
{
AutoreleasePool = objc_getRequiredClass("NSAutoreleasePool");
if (Nil == AutoreleasePool)
{
useARCAutoreleasePool = YES;
}
else
{
[AutoreleasePool class];
useARCAutoreleasePool = class_respondsToSelector(AutoreleasePool,
SELECTOR(_ARCCompatibleAutoreleasePool));
NewAutoreleasePool = class_getMethodImplementation(object_getClass(AutoreleasePool),
SELECTOR(new));
DeleteAutoreleasePool = class_getMethodImplementation(AutoreleasePool,
SELECTOR(release));
AutoreleaseAdd = class_getMethodImplementation(object_getClass(AutoreleasePool),
SELECTOR(addObject:));
}
}
if (useARCAutoreleasePool) if (useARCAutoreleasePool)
{ {
struct arc_tls* tls = getARCThreadData(); struct arc_tls* tls = getARCThreadData();
@ -239,6 +247,8 @@ void *objc_autoreleasePoolPush(void)
return (NULL != tls->pool) ? tls->pool->insert : NULL; return (NULL != tls->pool) ? tls->pool->insert : NULL;
} }
} }
initAutorelease();
if (0 == NewAutoreleasePool) { return NULL; }
return NewAutoreleasePool(AutoreleasePool, SELECTOR(new)); return NewAutoreleasePool(AutoreleasePool, SELECTOR(new));
} }
void objc_autoreleasePoolPop(void *pool) void objc_autoreleasePoolPop(void *pool)
@ -253,8 +263,6 @@ void objc_autoreleasePoolPop(void *pool)
return; return;
} }
} }
// TODO: Keep a small pool of autorelease pools per thread and allocate
// from there.
DeleteAutoreleasePool(pool, SELECTOR(release)); DeleteAutoreleasePool(pool, SELECTOR(release));
struct arc_tls* tls = getARCThreadData(); struct arc_tls* tls = getARCThreadData();
if (tls && tls->returnRetained) if (tls && tls->returnRetained)

Loading…
Cancel
Save