Chromium Code Reviews| Index: chrome/browser/ui/cocoa/objc_zombie.mm |
| diff --git a/chrome/browser/ui/cocoa/objc_zombie.mm b/chrome/browser/ui/cocoa/objc_zombie.mm |
| index 31d2a62a9f4d6c1ddbd121963dc02c57e8c5cc32..452789cb29ceb8b744670cbb95fcb1087e10242c 100644 |
| --- a/chrome/browser/ui/cocoa/objc_zombie.mm |
| +++ b/chrome/browser/ui/cocoa/objc_zombie.mm |
| @@ -33,12 +33,13 @@ |
| namespace { |
| -// |object_cxxDestruct()| is an Objective-C runtime function which |
| -// traverses the object's class tree for ".cxxdestruct" methods which |
| -// are run to call C++ destructors as part of |-dealloc|. The |
| -// function is not public, so must be looked up using nlist. |
| +// Function which destroys the contents of an object without freeing |
| +// the object. On 10.5 this is |object_cxxDestruct()|, which |
| +// traverses the class hierarchy to run the C++ destructors. On 10.6 |
| +// this is |objc_destructInstance()| which calls |
| +// |object_cxxDestruct()| and removes associative references. |
| typedef void DestructFn(id obj); |
|
Mark Mentovai
2011/05/28 13:20:46
Technically the function pointer types are incompa
Scott Hess - ex-Googler
2011/05/31 20:22:30
Augmented the comment to that end.
|
| -DestructFn* g_object_cxxDestruct = NULL; |
| +DestructFn* g_objectDestruct = NULL; |
| // The original implementation for |-[NSObject dealloc]|. |
| IMP g_originalDeallocIMP = NULL; |
| @@ -70,9 +71,9 @@ typedef struct { |
| ZombieRecord* g_zombies = NULL; |
| -// Lookup the private |object_cxxDestruct| function and return a |
| -// pointer to it. Returns |NULL| on failure. |
| -DestructFn* LookupObjectCxxDestruct() { |
| +// Lookup the private object destruction function and return a pointer |
| +// to it. Returns |NULL| on failure. |
| +DestructFn* LookupObjectDestruct() { |
| #if ARCH_CPU_64_BITS |
|
Mark Mentovai
2011/05/28 13:20:46
Put this below the dlsym (but keep it before the n
Scott Hess - ex-Googler
2011/05/31 20:22:30
You sure? I think it's the right long-term decisi
Mark Mentovai
2011/05/31 21:00:57
shess wrote:
Scott Hess - ex-Googler
2011/06/07 21:24:51
Done. AFAICT, nlist() isn't present for 64-bit, a
|
| // TODO(shess): Port to 64-bit. I believe using struct nlist_64 |
| // will suffice. http://crbug.com/44021 . |
| @@ -80,6 +81,10 @@ DestructFn* LookupObjectCxxDestruct() { |
| return NULL; |
| #endif |
| + void* fn = dlsym(RTLD_DEFAULT, "objc_destructInstance"); |
|
Mark Mentovai
2011/05/29 22:02:31
RTLD_DEFAULT kind of sucks for a few reasons. It’l
Scott Hess - ex-Googler
2011/05/31 20:22:30
Done. I do not know what I'm doing in this area,
|
| + if (fn) |
| + return (DestructFn*)fn; |
|
Scott Hess - ex-Googler
2011/05/28 05:44:35
I need to clean up the casting in this function, a
Scott Hess - ex-Googler
2011/05/31 20:22:30
OK, casting is so annoying that I'm not sure I'm d
|
| + |
| struct nlist nl[3]; |
|
Mark Mentovai
2011/05/29 22:02:31
If we can’t find objc_destructInstance with dlsym
Scott Hess - ex-Googler
2011/05/31 20:22:30
Earlier when I put in the whitelist, I left it way
Mark Mentovai
2011/05/31 21:00:57
shess wrote:
|
| bzero(&nl, sizeof(nl)); |
| @@ -109,12 +114,12 @@ void ZombieDealloc(id self, SEL _cmd) { |
| return; |
| } |
| - // Use the original |-dealloc| if |object_cxxDestruct| was never |
| + // Use the original |-dealloc| if |g_objectDestruct| was never |
| // initialized, because otherwise C++ destructors won't be called. |
| // This case should be impossible, but doing it wrong would cause |
| // terrible problems. |
| - DCHECK(g_object_cxxDestruct); |
| - if (!g_object_cxxDestruct) { |
| + DCHECK(g_objectDestruct); |
| + if (!g_objectDestruct) { |
| g_originalDeallocIMP(self, _cmd); |
| return; |
| } |
| @@ -124,7 +129,11 @@ void ZombieDealloc(id self, SEL _cmd) { |
| // Destroy the instance by calling C++ destructors and clearing it |
| // to something unlikely to work well if someone references it. |
| - (*g_object_cxxDestruct)(self); |
| + // NOTE(shess): |object_dispose()| will call this again when the |
| + // zombie falls off the treadmill! But by then |isa| will be a |
| + // class without C++ destructors or associative references, so it |
| + // won't hurt anything. |
|
Scott Hess - ex-Googler
2011/05/28 05:44:35
Sorry, I think this comment snuck over when I brok
Mark Mentovai
2011/05/28 13:20:46
shess wrote:
|
| + (*g_objectDestruct)(self); |
| memset(self, '!', size); |
| // If the instance is big enough, make it into a fat zombie and have |
| @@ -219,7 +228,7 @@ BOOL ZombieInit() { |
| Class rootClass = [NSObject class]; |
| - g_object_cxxDestruct = LookupObjectCxxDestruct(); |
| + g_objectDestruct = LookupObjectDestruct(); |
| g_originalDeallocIMP = |
| class_getMethodImplementation(rootClass, @selector(dealloc)); |
| // objc_getClass() so CrZombie doesn't need +class. |
| @@ -227,7 +236,7 @@ BOOL ZombieInit() { |
| g_fatZombieClass = objc_getClass("CrFatZombie"); |
| g_fatZombieSize = class_getInstanceSize(g_fatZombieClass); |
| - if (!g_object_cxxDestruct || !g_originalDeallocIMP || |
| + if (!g_objectDestruct || !g_originalDeallocIMP || |
| !g_zombieClass || !g_fatZombieClass) |
| return NO; |