-
Notifications
You must be signed in to change notification settings - Fork 517
/
Copy pathconsolidatePoolPointers.m
143 lines (119 loc) · 3.99 KB
/
consolidatePoolPointers.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//TEST_CONFIG MEM=mrc ARCH=x86_64,arm64,arm64e
//TEST_ENV OBJC_DISABLE_AUTORELEASE_COALESCING=NO OBJC_DISABLE_AUTORELEASE_COALESCING_LRU=NO
#include "test.h"
#import <objc/NSObject.h>
@interface Counter: NSObject {
@public
int retains;
int releases;
int autoreleases;
}
@end
@implementation Counter
- (id)retain {
retains++;
return [super retain];
}
- (oneway void)release {
releases++;
[super release];
}
- (id)autorelease {
autoreleases++;
return [super autorelease];
}
- (void)dealloc {
testprintf("%p dealloc\n", self);
[super dealloc];
}
@end
// Create a number of objects, autoreleasing each one a number of times in a
// round robin fashion. Verify that each object gets sent retain, release, and
// autorelease the correct number of times. Verify that the gap between
// autoreleasepool pointers is the given number of objects. Note: this will not
// work when the pool hits a page boundary, to be sure to stay under that limit.
void test(int objCount, int autoreleaseCount, int expectedGap) {
testprintf("Testing %d objects, %d autoreleases, expecting gap of %d\n",
objCount, autoreleaseCount, expectedGap);
Counter *objs[objCount];
for (int i = 0; i < objCount; i++)
objs[i] = [Counter new];
for (int j = 0; j < autoreleaseCount; j++)
for (int i = 0; i < objCount; i++)
[objs[i] retain];
for (int i = 0; i < objCount; i++) {
testassertequal(objs[i]->retains, autoreleaseCount);
testassertequal(objs[i]->releases, 0);
testassertequal(objs[i]->autoreleases, 0);
}
void *outer = objc_autoreleasePoolPush();
uintptr_t outerAddr = (uintptr_t)outer;
for (int j = 0; j < autoreleaseCount; j++)
for (int i = 0; i < objCount; i++)
[objs[i] autorelease];
for (int i = 0; i < objCount; i++) {
testassertequal(objs[i]->retains, autoreleaseCount);
testassertequal(objs[i]->releases, 0);
testassertequal(objs[i]->autoreleases, autoreleaseCount);
}
void *inner = objc_autoreleasePoolPush();
uintptr_t innerAddr = (uintptr_t)inner;
testprintf("outer=%p inner=%p\n", outer, inner);
// Do one more autorelease in the inner pool to make sure we correctly
// handle pool boundaries.
for (int i = 0; i < objCount; i++)
[[objs[i] retain] autorelease];
// Flush any stale autorelease TLS entries.
objc_autoreleasePoolPop(objc_autoreleasePoolPush());
for (int i = 0; i < objCount; i++) {
testassertequal(objs[i]->retains, autoreleaseCount + 1);
testassertequal(objs[i]->releases, 0);
testassertequal(objs[i]->autoreleases, autoreleaseCount + 1);
}
objc_autoreleasePoolPop(inner);
for (int i = 0; i < objCount; i++) {
testassertequal(objs[i]->retains, autoreleaseCount + 1);
testassertequal(objs[i]->releases, 1);
testassertequal(objs[i]->autoreleases, autoreleaseCount + 1);
}
objc_autoreleasePoolPop(outer);
for (int i = 0; i < objCount; i++) {
testassertequal(objs[i]->retains, autoreleaseCount + 1);
testassertequal(objs[i]->releases, autoreleaseCount + 1);
testassertequal(objs[i]->autoreleases, autoreleaseCount + 1);
}
intptr_t gap = innerAddr - outerAddr;
testprintf("gap=%ld\n", gap);
testassertequal(gap, expectedGap * sizeof(id));
// Destroy our test objects.
for (int i = 0; i < objCount; i++)
[objs[i] release];
}
int main()
{
// Push a pool here so test() doesn't see a placeholder.
objc_autoreleasePoolPush();
test(1, 1, 2);
test(1, 2, 2);
test(1, 10, 2);
test(1, 100, 2);
test(1, 70000, 3);
test(2, 1, 3);
test(2, 2, 3);
test(2, 10, 3);
test(2, 100, 3);
test(2, 70000, 5);
test(3, 1, 4);
test(3, 2, 4);
test(3, 10, 4);
test(3, 100, 4);
test(3, 70000, 7);
test(4, 1, 5);
test(4, 2, 5);
test(4, 10, 5);
test(4, 100, 5);
test(4, 70000, 9);
test(5, 1, 6);
test(5, 2, 11);
succeed(__FILE__);
}