Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian Menschel committed Apr 16, 2016
2 parents 1e6a659 + 1962c0c commit 9110a4f
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 28 deletions.
6 changes: 6 additions & 0 deletions HeapInspector/HINSPDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ NS_ASSUME_NONNULL_BEGIN
/// Stops the HeapInspector and removes the inspector's view
+ (void)stop;

// Shows HeapInspector (if not visible yet) and starts the record immediately
+ (void)startRecord;

// Stops record - but does not hide the HeapInspector
+ (void)stopRecord;

/// Add some (or only one) class prefix like `UI` OR `MK` to record classes that match the prefix only.
/// It's highly recommended to record a specific class or prefix -
/// otherwise all Cocoa classes will be recorded, which slows down the performance.
Expand Down
14 changes: 14 additions & 0 deletions HeapInspector/HINSPDebug.m
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ - (HINSPHeapStackTableViewController *)heapStackControllerWithHeapStack:(NSArray

- (void)stopRecord
{
_window.recordButton.isRecording = NO;
_recordedHeap = [HINSPHeapStackInspector recordedHeap];
[self showInfoLabel];
[NSObject endSnapshot];
Expand All @@ -128,6 +129,7 @@ - (void)beginRecord
_recordedHeap = nil;
[self resetInfoLabel];
[NSObject beginSnapshot];
_window.recordButton.isRecording = YES;
[HINSPHeapStackInspector performHeapShot];
}

Expand All @@ -138,6 +140,14 @@ + (void)start
twDebug = [[HINSPDebug alloc] init];
}

+ (void)startRecord
{
if (!twDebug) {
[self start];
}
[twDebug beginRecord];
}

+ (void)stop
{
[NSObject endSnapshot];
Expand All @@ -146,6 +156,10 @@ + (void)stop
twDebug = nil;
}

+ (void)stopRecord {
[twDebug stopRecord];
}

+ (void)addClassPrefixesToRecord:(NSArray <NSString *> *)classPrefixes
{
if (classPrefixes) {
Expand Down
5 changes: 4 additions & 1 deletion HeapInspector/HINSPHeapStackDetailTableViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ - (void)updateHeaderView
{
if ([self.inspectingObject conformsToProtocol:@protocol(NSObject)] &&
[self.inspectingObject respondsToSelector:@selector(description)]) {
_headerTextView.text = [self.inspectingObject description];
NSInteger retainCount = CFGetRetainCount((__bridge CFTypeRef)self.inspectingObject);
NSString *retainCountString = [NSString stringWithFormat:@"Retain count: %ld\n", (long)retainCount];
NSString *infoHeaderText = [retainCountString stringByAppendingString:[self.inspectingObject description]];
_headerTextView.text = infoHeaderText;
}
}

Expand Down
2 changes: 1 addition & 1 deletion HeapInspector/HINSPHeapStackInspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#import <Foundation/Foundation.h>

typedef void (^RMHeapEnumeratorBlock)(__unsafe_unretained id object);
typedef void (^RMHeapEnumeratorBlock)(__unsafe_unretained id object, BOOL *stop);

@interface HINSPHeapStackInspector : NSObject

Expand Down
46 changes: 31 additions & 15 deletions HeapInspector/HINSPHeapStackInspector.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ static inline void range_callback(task_t task,
vm_range_t *ranges,
unsigned rangeCount)
{
RMHeapEnumeratorBlock block = (__bridge RMHeapEnumeratorBlock)context;
if (!block) {
RMHeapEnumeratorBlock enumeratorBlock = (__bridge RMHeapEnumeratorBlock)context;
if (!enumeratorBlock) {
return;
}
BOOL stop = NO;
for (unsigned int i = 0; i < rangeCount; i++) {
vm_range_t range = ranges[i];
rm_maybe_object_t *object = (rm_maybe_object_t *)range.address;
Expand All @@ -55,20 +56,23 @@ static inline void range_callback(task_t task,
if (tryClass &&
CFSetContainsValue(classesLoadedInRuntime, (__bridge const void *)(tryClass)) &&
canRecordObject((__bridge id)object)) {
block((__bridge id)object);
enumeratorBlock((__bridge id)object, &stop);
if (stop) {
break;
}
}
}
}

+ (void)enumerateLiveObjectsUsingBlock:(RMHeapEnumeratorBlock)block
+ (void)enumerateLiveObjectsUsingBlock:(RMHeapEnumeratorBlock)completionBlock
{
if (!block) {
if (!completionBlock) {
return;
}

// Refresh the class list on every call in case classes are added to the runtime.
[self updateRegisteredClasses];

// For another exmple of enumerating through malloc ranges (which helped my understanding of the api) see:
// http://llvm.org/svn/llvm-project/lldb/tags/RELEASE_34/final/examples/darwin/heap_find/heap/heap_find.cpp
// Also https://gist.github.com/samdmarshall/17f4e66b5e2e579fd396
Expand All @@ -77,16 +81,27 @@ + (void)enumerateLiveObjectsUsingBlock:(RMHeapEnumeratorBlock)block
mach_port_t task = mach_task_self();
unsigned int zoneCount = 0;
kern_return_t result = malloc_get_all_zones(task, memory_reader, &zones, &zoneCount);
BOOL __block stopEnumerator = NO;
if (result == KERN_SUCCESS) {
for (unsigned i = 0; i < zoneCount; i++) {
malloc_zone_t *zone = (malloc_zone_t *)zones[i];
if (zone != NULL && zone->introspect != NULL) {
zone->introspect->enumerator(task,
(__bridge void *)(block),
MALLOC_PTR_IN_USE_RANGE_TYPE,
(vm_address_t)zone,
memory_reader,
range_callback);
RMHeapEnumeratorBlock enumeratorBlock = ^(__unsafe_unretained id object, BOOL *stop) {
completionBlock(object, &stopEnumerator);
if (stopEnumerator) {
*stop = YES;
}
};
if (!stopEnumerator) {
zone->introspect->enumerator(task,
(__bridge void *)(enumeratorBlock),
MALLOC_PTR_IN_USE_RANGE_TYPE,
(vm_address_t)zone,
memory_reader,
range_callback);
} else {
break;
}
}
}
}
Expand Down Expand Up @@ -132,7 +147,7 @@ + (NSSet *)recordedHeap
+ (NSSet *)heap
{
NSMutableSet *objects = [NSMutableSet set];
[HINSPHeapStackInspector enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object) {
[HINSPHeapStackInspector enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, BOOL *stop) {
// We cannot store the object itself - We want to avoid any retain calls.
// We store the class name + pointer
NSString *string = [NSString stringWithFormat:@"%s: %p",
Expand All @@ -147,12 +162,13 @@ + (NSSet *)heap
+ (id)objectForPointer:(NSString *)pointer
{
id __block foundObject = nil;
[HINSPHeapStackInspector enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object) {
[HINSPHeapStackInspector enumerateLiveObjectsUsingBlock:^(__unsafe_unretained id object, BOOL *stop) {
if ([pointer isEqualToString:[NSString stringWithFormat:@"%p",object]]) {

foundObject = object;
*stop = YES;
}
}];

return foundObject;
}

Expand Down
2 changes: 1 addition & 1 deletion HeapInspector/HINSPRecordButton.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
#import <UIKit/UIKit.h>

@interface HINSPRecordButton : UIControl

@property (nonatomic) BOOL isRecording;
@end
20 changes: 12 additions & 8 deletions HeapInspector/HINSPRecordButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@


@interface HINSPRecordButton ()

@property (nonatomic) BOOL isRecording;
@property (nonatomic, weak) CAShapeLayer *shapeLayer;
@end

Expand All @@ -31,13 +29,19 @@ - (instancetype)initWithFrame:(CGRect)frame
- (void)tapped:(id)sender
{
self.isRecording = !self.isRecording;
UIColor *color = nil;
if (self.isRecording) {
color = [self recordingColor];
} else {
color = [self defaultColor];
}

- (void)setIsRecording:(BOOL)isRecording {
if (_isRecording != isRecording) {
_isRecording = isRecording;
UIColor *color = nil;
if (isRecording) {
color = [self recordingColor];
} else {
color = [self defaultColor];
}
_shapeLayer.fillColor = color.CGColor;
}
_shapeLayer.fillColor = color.CGColor;
}

#pragma mark - Setter
Expand Down
2 changes: 1 addition & 1 deletion HeapInspector/HINSPRefHistoryTableViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ - (instancetype)initWithObject:(id)object
self = [super initWithObject:object];
if (self) {

self.title = [NSString stringWithFormat:@"Reference History: %s: %p",
self.title = [NSString stringWithFormat:@"%s: %p",
object_getClassName(self.inspectingObject),
self.inspectingObject];

Expand Down
2 changes: 1 addition & 1 deletion HeapInspector/HINSPShowViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ - (instancetype)initWithObject:(id)object
self = [super init];
if (self) {
self.title = @"Showing View";
self.edgesForExtendedLayout = UIRectEdgeNone;
self.automaticallyAdjustsScrollViewInsets = YES;
_objectToInspect = object;
self.shouldShowEditButton = YES;
}
Expand Down

0 comments on commit 9110a4f

Please sign in to comment.