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; |