@@ -37,10 +37,11 @@ static inline void range_callback(task_t task,
3737 vm_range_t *ranges,
3838 unsigned rangeCount)
3939{
40- RMHeapEnumeratorBlock block = (__bridge RMHeapEnumeratorBlock)context;
41- if (!block ) {
40+ RMHeapEnumeratorBlock enumeratorBlock = (__bridge RMHeapEnumeratorBlock)context;
41+ if (!enumeratorBlock ) {
4242 return ;
4343 }
44+ BOOL stop = NO ;
4445 for (unsigned int i = 0 ; i < rangeCount; i++) {
4546 vm_range_t range = ranges[i];
4647 rm_maybe_object_t *object = (rm_maybe_object_t *)range.address ;
@@ -55,20 +56,23 @@ static inline void range_callback(task_t task,
5556 if (tryClass &&
5657 CFSetContainsValue (classesLoadedInRuntime, (__bridge const void *)(tryClass)) &&
5758 canRecordObject ((__bridge id )object)) {
58- block ((__bridge id )object);
59+ enumeratorBlock ((__bridge id )object, &stop);
60+ if (stop) {
61+ break ;
62+ }
5963 }
6064 }
6165}
6266
63- + (void )enumerateLiveObjectsUsingBlock : (RMHeapEnumeratorBlock)block
67+ + (void )enumerateLiveObjectsUsingBlock : (RMHeapEnumeratorBlock)completionBlock
6468{
65- if (!block ) {
69+ if (!completionBlock ) {
6670 return ;
6771 }
6872
6973 // Refresh the class list on every call in case classes are added to the runtime.
7074 [self updateRegisteredClasses ];
71-
75+
7276 // For another exmple of enumerating through malloc ranges (which helped my understanding of the api) see:
7377 // http://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final/examples/darwin/heap_find/heap/heap_find.cpp
7478 // Also https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396
@@ -77,16 +81,27 @@ + (void)enumerateLiveObjectsUsingBlock:(RMHeapEnumeratorBlock)block
7781 mach_port_t task = mach_task_self ();
7882 unsigned int zoneCount = 0 ;
7983 kern_return_t result = malloc_get_all_zones (task, memory_reader, &zones, &zoneCount);
84+ BOOL __block stopEnumerator = NO ;
8085 if (result == KERN_SUCCESS) {
8186 for (unsigned i = 0 ; i < zoneCount; i++) {
8287 malloc_zone_t *zone = (malloc_zone_t *)zones[i];
8388 if (zone != NULL && zone->introspect != NULL ) {
84- zone->introspect ->enumerator (task,
85- (__bridge void *)(block),
86- MALLOC_PTR_IN_USE_RANGE_TYPE,
87- (vm_address_t )zone,
88- memory_reader,
89- range_callback);
89+ RMHeapEnumeratorBlock enumeratorBlock = ^(__unsafe_unretained id object, BOOL *stop) {
90+ completionBlock (object, &stopEnumerator);
91+ if (stopEnumerator) {
92+ *stop = YES ;
93+ }
94+ };
95+ if (!stopEnumerator) {
96+ zone->introspect ->enumerator (task,
97+ (__bridge void *)(enumeratorBlock),
98+ MALLOC_PTR_IN_USE_RANGE_TYPE,
99+ (vm_address_t )zone,
100+ memory_reader,
101+ range_callback);
102+ } else {
103+ break ;
104+ }
90105 }
91106 }
92107 }
@@ -132,7 +147,7 @@ + (NSSet *)recordedHeap
132147+ (NSSet *)heap
133148{
134149 NSMutableSet *objects = [NSMutableSet set ];
135- [HINSPHeapStackInspector enumerateLiveObjectsUsingBlock: ^(__unsafe_unretained id object) {
150+ [HINSPHeapStackInspector enumerateLiveObjectsUsingBlock: ^(__unsafe_unretained id object, BOOL *stop ) {
136151 // We cannot store the object itself - We want to avoid any retain calls.
137152 // We store the class name + pointer
138153 NSString *string = [NSString stringWithFormat: @" %s : %p " ,
@@ -147,12 +162,13 @@ + (NSSet *)heap
147162+ (id )objectForPointer : (NSString *)pointer
148163{
149164 id __block foundObject = nil ;
150- [HINSPHeapStackInspector enumerateLiveObjectsUsingBlock: ^(__unsafe_unretained id object) {
165+ [HINSPHeapStackInspector enumerateLiveObjectsUsingBlock: ^(__unsafe_unretained id object, BOOL *stop ) {
151166 if ([pointer isEqualToString: [NSString stringWithFormat: @" %p " ,object]]) {
167+
152168 foundObject = object;
169+ *stop = YES ;
153170 }
154171 }];
155-
156172 return foundObject;
157173}
158174
0 commit comments