Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(160)

Side by Side Diff: chrome/common/mac/objc_zombie.mm

Issue 8468018: chrome: Remove 10 exit time destructors and 2 static initializers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: duh Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/common/extensions/extension_l10n_util.cc ('k') | chrome/common/metrics_helpers.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/common/mac/objc_zombie.h" 5 #import "chrome/common/mac/objc_zombie.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #include <execinfo.h> 8 #include <execinfo.h>
9 #include <mach-o/dyld.h> 9 #include <mach-o/dyld.h>
10 #include <mach-o/nlist.h> 10 #include <mach-o/nlist.h>
11 11
12 #import <objc/objc-class.h> 12 #import <objc/objc-class.h>
13 13
14 #include <algorithm> 14 #include <algorithm>
15 #include <iostream> 15 #include <iostream>
16 16
17 #include "base/debug/stack_trace.h" 17 #include "base/debug/stack_trace.h"
18 #include "base/lazy_instance.h"
18 #include "base/logging.h" 19 #include "base/logging.h"
19 #include "base/mac/crash_logging.h" 20 #include "base/mac/crash_logging.h"
20 #include "base/mac/mac_util.h" 21 #include "base/mac/mac_util.h"
21 #include "base/metrics/histogram.h" 22 #include "base/metrics/histogram.h"
22 #include "base/synchronization/lock.h" 23 #include "base/synchronization/lock.h"
23 #import "chrome/common/mac/objc_method_swizzle.h" 24 #import "chrome/common/mac/objc_method_swizzle.h"
24 25
25 // Deallocated objects are re-classed as |CrZombie|. No superclass 26 // Deallocated objects are re-classed as |CrZombie|. No superclass
26 // because then the class would have to override many/most of the 27 // because then the class would have to override many/most of the
27 // inherited methods (|NSObject| is like a category magnet!). 28 // inherited methods (|NSObject| is like a category magnet!).
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 // treadmill). 69 // treadmill).
69 Class g_zombieClass = Nil; // cached [CrZombie class] 70 Class g_zombieClass = Nil; // cached [CrZombie class]
70 Class g_fatZombieClass = Nil; // cached [CrFatZombie class] 71 Class g_fatZombieClass = Nil; // cached [CrFatZombie class]
71 size_t g_fatZombieSize = 0; 72 size_t g_fatZombieSize = 0;
72 73
73 // Whether to zombie all freed objects, or only those which return YES 74 // Whether to zombie all freed objects, or only those which return YES
74 // from |-shouldBecomeCrZombie|. 75 // from |-shouldBecomeCrZombie|.
75 BOOL g_zombieAllObjects = NO; 76 BOOL g_zombieAllObjects = NO;
76 77
77 // Protects |g_zombieCount|, |g_zombieIndex|, and |g_zombies|. 78 // Protects |g_zombieCount|, |g_zombieIndex|, and |g_zombies|.
78 base::Lock lock_; 79 base::LazyInstance<base::Lock, base::LeakyLazyInstanceTraits<base::Lock> >
80 g_lock = LAZY_INSTANCE_INITIALIZER;
79 81
80 // How many zombies to keep before freeing, and the current head of 82 // How many zombies to keep before freeing, and the current head of
81 // the circular buffer. 83 // the circular buffer.
82 size_t g_zombieCount = 0; 84 size_t g_zombieCount = 0;
83 size_t g_zombieIndex = 0; 85 size_t g_zombieIndex = 0;
84 86
85 typedef struct { 87 typedef struct {
86 id object; // The zombied object. 88 id object; // The zombied object.
87 Class wasa; // Value of |object->isa| before we replaced it. 89 Class wasa; // Value of |object->isa| before we replaced it.
88 void* trace[kBacktraceDepth]; // Backtrace at point of deallocation. 90 void* trace[kBacktraceDepth]; // Backtrace at point of deallocation.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 } 208 }
207 209
208 // The new record to swap into |g_zombies|. If |g_zombieCount| is 210 // The new record to swap into |g_zombies|. If |g_zombieCount| is
209 // zero, then |self| will be freed immediately. 211 // zero, then |self| will be freed immediately.
210 ZombieRecord zombieToFree = {self, wasa}; 212 ZombieRecord zombieToFree = {self, wasa};
211 zombieToFree.traceDepth = 213 zombieToFree.traceDepth =
212 std::max(backtrace(zombieToFree.trace, kBacktraceDepth), 0); 214 std::max(backtrace(zombieToFree.trace, kBacktraceDepth), 0);
213 215
214 // Don't involve the lock when creating zombies without a treadmill. 216 // Don't involve the lock when creating zombies without a treadmill.
215 if (g_zombieCount > 0) { 217 if (g_zombieCount > 0) {
216 base::AutoLock pin(lock_); 218 base::AutoLock pin(g_lock.Get());
217 219
218 // Check the count again in a thread-safe manner. 220 // Check the count again in a thread-safe manner.
219 if (g_zombieCount > 0) { 221 if (g_zombieCount > 0) {
220 // Put the current object on the treadmill and keep the previous 222 // Put the current object on the treadmill and keep the previous
221 // occupant. 223 // occupant.
222 std::swap(zombieToFree, g_zombies[g_zombieIndex]); 224 std::swap(zombieToFree, g_zombies[g_zombieIndex]);
223 225
224 // Bump the index forward. 226 // Bump the index forward.
225 g_zombieIndex = (g_zombieIndex + 1) % g_zombieCount; 227 g_zombieIndex = (g_zombieIndex + 1) % g_zombieCount;
226 } 228 }
227 } 229 }
228 230
229 // Do the free out here to prevent any chance of deadlock. 231 // Do the free out here to prevent any chance of deadlock.
230 if (zombieToFree.object) 232 if (zombieToFree.object)
231 object_dispose(zombieToFree.object); 233 object_dispose(zombieToFree.object);
232 } 234 }
233 235
234 // Search the treadmill for |object| and fill in |*record| if found. 236 // Search the treadmill for |object| and fill in |*record| if found.
235 // Returns YES if found. 237 // Returns YES if found.
236 BOOL GetZombieRecord(id object, ZombieRecord* record) { 238 BOOL GetZombieRecord(id object, ZombieRecord* record) {
237 // Holding the lock is reasonable because this should be fast, and 239 // Holding the lock is reasonable because this should be fast, and
238 // the process is going to crash presently anyhow. 240 // the process is going to crash presently anyhow.
239 base::AutoLock pin(lock_); 241 base::AutoLock pin(g_lock.Get());
240 for (size_t i = 0; i < g_zombieCount; ++i) { 242 for (size_t i = 0; i < g_zombieCount; ++i) {
241 if (g_zombies[i].object == object) { 243 if (g_zombies[i].object == object) {
242 *record = g_zombies[i]; 244 *record = g_zombies[i];
243 return YES; 245 return YES;
244 } 246 }
245 } 247 }
246 return NO; 248 return NO;
247 } 249 }
248 250
249 // Dump the symbols. This is pulled out into a function to make it 251 // Dump the symbols. This is pulled out into a function to make it
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 const IMP prevDeallocIMP = method_setImplementation(m, (IMP)ZombieDealloc); 467 const IMP prevDeallocIMP = method_setImplementation(m, (IMP)ZombieDealloc);
466 DCHECK(prevDeallocIMP == g_originalDeallocIMP || 468 DCHECK(prevDeallocIMP == g_originalDeallocIMP ||
467 prevDeallocIMP == (IMP)ZombieDealloc); 469 prevDeallocIMP == (IMP)ZombieDealloc);
468 470
469 // Grab the current set of zombies. This is thread-safe because 471 // Grab the current set of zombies. This is thread-safe because
470 // only the main thread can change these. 472 // only the main thread can change these.
471 const size_t oldCount = g_zombieCount; 473 const size_t oldCount = g_zombieCount;
472 ZombieRecord* oldZombies = g_zombies; 474 ZombieRecord* oldZombies = g_zombies;
473 475
474 { 476 {
475 base::AutoLock pin(lock_); 477 base::AutoLock pin(g_lock.Get());
476 478
477 // Save the old index in case zombies need to be transferred. 479 // Save the old index in case zombies need to be transferred.
478 size_t oldIndex = g_zombieIndex; 480 size_t oldIndex = g_zombieIndex;
479 481
480 // Create the new zombie treadmill, disabling zombies in case of 482 // Create the new zombie treadmill, disabling zombies in case of
481 // failure. 483 // failure.
482 g_zombieIndex = 0; 484 g_zombieIndex = 0;
483 g_zombieCount = zombieCount; 485 g_zombieCount = zombieCount;
484 g_zombies = NULL; 486 g_zombies = NULL;
485 if (g_zombieCount) { 487 if (g_zombieCount) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 // Put back the original implementation of -[NSObject dealloc]. 538 // Put back the original implementation of -[NSObject dealloc].
537 Method m = class_getInstanceMethod([NSObject class], @selector(dealloc)); 539 Method m = class_getInstanceMethod([NSObject class], @selector(dealloc));
538 DCHECK(m); 540 DCHECK(m);
539 method_setImplementation(m, g_originalDeallocIMP); 541 method_setImplementation(m, g_originalDeallocIMP);
540 542
541 // Can safely grab this because it only happens on the main thread. 543 // Can safely grab this because it only happens on the main thread.
542 const size_t oldCount = g_zombieCount; 544 const size_t oldCount = g_zombieCount;
543 ZombieRecord* oldZombies = g_zombies; 545 ZombieRecord* oldZombies = g_zombies;
544 546
545 { 547 {
546 base::AutoLock pin(lock_); // In case any |-dealloc| are in-progress. 548 base::AutoLock pin(g_lock.Get()); // In case any -dealloc are in progress.
547 g_zombieCount = 0; 549 g_zombieCount = 0;
548 g_zombies = NULL; 550 g_zombies = NULL;
549 } 551 }
550 552
551 // Free any remaining zombies. 553 // Free any remaining zombies.
552 if (oldZombies) { 554 if (oldZombies) {
553 for (size_t i = 0; i < oldCount; ++i) { 555 for (size_t i = 0; i < oldCount; ++i) {
554 if (oldZombies[i].object) 556 if (oldZombies[i].object)
555 object_dispose(oldZombies[i].object); 557 object_dispose(oldZombies[i].object);
556 } 558 }
557 free(oldZombies); 559 free(oldZombies);
558 } 560 }
559 } 561 }
560 562
561 } // namespace ObjcEvilDoers 563 } // namespace ObjcEvilDoers
OLDNEW
« no previous file with comments | « chrome/common/extensions/extension_l10n_util.cc ('k') | chrome/common/metrics_helpers.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698