Summary: This diff adds a new experimental checker for detecting size of objects in autorelease pool in ObjC. The basic mechanism is almost the same with the previous cost calculation: * Autorelease pool size is increased at explicit `autorelease` call * Autorelease pool size is set as zero by the `autoreleasepool` block. While it only supports the explicit calls as of now, we will extend the checker to handle more cases in the following diffs. Reviewed By: ezgicicek Differential Revision: D23473145 fbshipit-source-id: 416488176master
parent
4dbfb72260
commit
cb4cf115e1
@ -0,0 +1,19 @@
|
||||
# Copyright (c) Facebook, Inc. and its affiliates.
|
||||
#
|
||||
# This source code is licensed under the MIT license found in the
|
||||
# LICENSE file in the root directory of this source tree.
|
||||
|
||||
TESTS_DIR = ../../..
|
||||
|
||||
CLANG_OPTIONS = -c $(OBJC_CLANG_OPTIONS)
|
||||
INFER_OPTIONS = --cost-only --debug-exceptions --project-root $(TESTS_DIR)
|
||||
INFERPRINT_OPTIONS = --issues-tests
|
||||
INFERPRINT_COST_OPTIONS = --cost-tests-only-autoreleasepool --cost-issues-tests
|
||||
|
||||
SOURCES = $(wildcard *.m)
|
||||
|
||||
include $(TESTS_DIR)/clang.make
|
||||
include $(TESTS_DIR)/objc.make
|
||||
include $(TESTS_DIR)/cost.make
|
||||
|
||||
infer-out/report.json: $(MAKEFILE_LIST)
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Basic : NSObject
|
||||
@end
|
||||
|
||||
@implementation Basic
|
||||
|
||||
- (void)call_autorelease_constant {
|
||||
NSString* x = [[NSString alloc] initWith:"test"];
|
||||
return [x autorelease];
|
||||
}
|
||||
|
||||
- (void)autoreleased_in_loop_linear:(int)n {
|
||||
for (int i = 0; i < n; i++) {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)autoreleased_in_autoreleasepool_zero:(int)n {
|
||||
for (int i = 0; i < n; i++) {
|
||||
@autoreleasepool {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is problematic because autoreleased objects inside the loop
|
||||
will not be released until the loop terminates. However, the checker is not
|
||||
measuring peak memory but size of autoreleasepool increased by the function.
|
||||
Since we wrap the loop inside the autoreleasepool block, we will be setting
|
||||
the size to 0 for the whole function. */
|
||||
- (void)loop_in_autoreleasepool_zero:(int)n {
|
||||
@autoreleasepool {
|
||||
for (int i = 0; i < n; i++) {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)autoreleased_in_loop_nested_zero:(int)n {
|
||||
@autoreleasepool {
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
@autoreleasepool {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)autoreleased_in_loop_sequential_constant:(int)n {
|
||||
@autoreleasepool {
|
||||
for (int i = 0; i < n; i++) {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
[self call_autorelease_constant];
|
||||
@autoreleasepool {
|
||||
for (int i = 0; i < n; i++) {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)autoreleased_in_loop_sequential_linear:(int)n {
|
||||
@autoreleasepool {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
for (int i = 0; i < n; i++) {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
@autoreleasepool {
|
||||
[self call_autorelease_constant];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)call_no_autorelease_zero {
|
||||
NSString* x = [[NSString alloc] initWith:"test"];
|
||||
return x;
|
||||
}
|
||||
|
||||
- (void)no_autoreleased_in_loop_zero:(int)n {
|
||||
for (int i = 0; i < n; i++) {
|
||||
[self call_no_autorelease];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,10 @@
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.autoreleased_in_autoreleasepool_zero:, 0, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.autoreleased_in_loop_linear:, n, OnUIThread:false, [{n},Loop]
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.autoreleased_in_loop_nested_zero:, 0, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.autoreleased_in_loop_sequential_constant:, 1, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.autoreleased_in_loop_sequential_linear:, n, OnUIThread:false, [{n},Loop]
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.call_autorelease_constant, 1, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.call_no_autorelease_zero, 0, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.dealloc, 0, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.loop_in_autoreleasepool_zero:, 0, OnUIThread:false, []
|
||||
codetoanalyze/objc/autoreleasepool/basic.m, Basic.no_autoreleased_in_loop_zero:, 0, OnUIThread:false, []
|
Loading…
Reference in new issue