]> git.saurik.com Git - apple/objc4.git/blob - test/rr-autorelease-fast.m
objc4-818.2.tar.gz
[apple/objc4.git] / test / rr-autorelease-fast.m
1 // TEST_CONFIG MEM=mrc
2 // TEST_CFLAGS -Os
3
4 #include "test.h"
5 #include "testroot.i"
6
7 #include <objc/objc-internal.h>
8 #include <objc/objc-abi.h>
9 #include <Foundation/Foundation.h>
10
11 @interface TestObject : TestRoot @end
12 @implementation TestObject @end
13
14
15 // MAGIC and NOT_MAGIC each call two functions
16 // with or without the magic instruction sequence, respectively.
17 //
18 // tmp = first(obj);
19 // magic, or not;
20 // tmp = second(tmp);
21
22 #if __arm__
23
24 #define NOT_MAGIC(first, second) \
25 tmp = first(obj); \
26 asm volatile("mov r8, r8"); \
27 tmp = second(tmp);
28
29 #define MAGIC(first, second) \
30 tmp = first(obj); \
31 asm volatile("mov r7, r7"); \
32 tmp = second(tmp);
33
34 // arm
35 #elif __arm64__
36
37 #define NOT_MAGIC(first, second) \
38 tmp = first(obj); \
39 asm volatile("mov x28, x28"); \
40 tmp = second(tmp);
41
42 #define MAGIC(first, second) \
43 tmp = first(obj); \
44 asm volatile("mov x29, x29"); \
45 tmp = second(tmp);
46
47 // arm64
48 #elif __x86_64__
49
50 #define NOT_MAGIC(first, second) \
51 tmp = first(obj); \
52 asm volatile("nop"); \
53 tmp = second(tmp);
54
55 #define MAGIC(first, second) \
56 tmp = first(obj); \
57 tmp = second(tmp);
58
59 // x86_64
60 #elif __i386__
61
62 #define NOT_MAGIC(first, second) \
63 tmp = first(obj); \
64 tmp = second(tmp);
65
66 #define MAGIC(first, second) \
67 asm volatile("\n subl $16, %%esp" \
68 "\n movl %[obj], (%%esp)" \
69 "\n call _" #first \
70 "\n" \
71 "\n movl %%ebp, %%ebp" \
72 "\n" \
73 "\n movl %%eax, (%%esp)" \
74 "\n call _" #second \
75 "\n movl %%eax, %[tmp]" \
76 "\n addl $16, %%esp" \
77 : [tmp] "=r" (tmp) \
78 : [obj] "r" (obj) \
79 : "eax", "edx", "ecx", "cc", "memory")
80
81 // i386
82 #else
83
84 #error unknown architecture
85
86 #endif
87
88
89 int
90 main()
91 {
92 TestObject *tmp, *obj;
93
94 #ifdef __x86_64__
95 // need to get DYLD to resolve the stubs on x86
96 PUSH_POOL {
97 TestObject *warm_up = [[TestObject alloc] init];
98 testassert(warm_up);
99 warm_up = objc_retainAutoreleasedReturnValue(warm_up);
100 warm_up = objc_unsafeClaimAutoreleasedReturnValue(warm_up);
101 [warm_up release];
102 warm_up = nil;
103 } POP_POOL;
104 #endif
105
106 testprintf(" Successful +1 -> +1 handshake\n");
107
108 PUSH_POOL {
109 obj = [[TestObject alloc] init];
110 testassert(obj);
111
112 TestRootRetain = 0;
113 TestRootRelease = 0;
114 TestRootAutorelease = 0;
115 TestRootDealloc = 0;
116
117 MAGIC(objc_autoreleaseReturnValue,
118 objc_retainAutoreleasedReturnValue);
119
120 testassert(TestRootDealloc == 0);
121 testassert(TestRootRetain == 0);
122 testassert(TestRootRelease == 0);
123 testassert(TestRootAutorelease == 0);
124
125 [tmp release];
126 testassert(TestRootDealloc == 1);
127 testassert(TestRootRetain == 0);
128 testassert(TestRootRelease == 1);
129 testassert(TestRootAutorelease == 0);
130
131 } POP_POOL;
132
133 testprintf("Unsuccessful +1 -> +1 handshake\n");
134
135 PUSH_POOL {
136 obj = [[TestObject alloc] init];
137 testassert(obj);
138
139 TestRootRetain = 0;
140 TestRootRelease = 0;
141 TestRootAutorelease = 0;
142 TestRootDealloc = 0;
143
144 NOT_MAGIC(objc_autoreleaseReturnValue,
145 objc_retainAutoreleasedReturnValue);
146
147 testassert(TestRootDealloc == 0);
148 testassert(TestRootRetain == 1);
149 testassert(TestRootRelease == 0);
150 testassert(TestRootAutorelease == 1);
151
152 [tmp release];
153 testassert(TestRootDealloc == 0);
154 testassert(TestRootRetain == 1);
155 testassert(TestRootRelease == 1);
156 testassert(TestRootAutorelease == 1);
157
158 } POP_POOL;
159 testassert(TestRootDealloc == 1);
160 testassert(TestRootRetain == 1);
161 testassert(TestRootRelease == 2);
162 testassert(TestRootAutorelease == 1);
163
164
165 testprintf(" Successful +0 -> +1 handshake\n");
166
167 PUSH_POOL {
168 obj = [[TestObject alloc] init];
169 testassert(obj);
170
171 TestRootRetain = 0;
172 TestRootRelease = 0;
173 TestRootAutorelease = 0;
174 TestRootDealloc = 0;
175
176 MAGIC(objc_retainAutoreleaseReturnValue,
177 objc_retainAutoreleasedReturnValue);
178
179 testassert(TestRootDealloc == 0);
180 testassert(TestRootRetain == 1);
181 testassert(TestRootRelease == 0);
182 testassert(TestRootAutorelease == 0);
183
184 [tmp release];
185 testassert(TestRootDealloc == 0);
186 testassert(TestRootRetain == 1);
187 testassert(TestRootRelease == 1);
188 testassert(TestRootAutorelease == 0);
189
190 [tmp release];
191 testassert(TestRootDealloc == 1);
192 testassert(TestRootRetain == 1);
193 testassert(TestRootRelease == 2);
194 testassert(TestRootAutorelease == 0);
195
196 } POP_POOL;
197
198 testprintf("Unsuccessful +0 -> +1 handshake\n");
199
200 PUSH_POOL {
201 obj = [[TestObject alloc] init];
202 testassert(obj);
203
204 TestRootRetain = 0;
205 TestRootRelease = 0;
206 TestRootAutorelease = 0;
207 TestRootDealloc = 0;
208
209 NOT_MAGIC(objc_retainAutoreleaseReturnValue,
210 objc_retainAutoreleasedReturnValue);
211
212 testassert(TestRootDealloc == 0);
213 testassert(TestRootRetain == 2);
214 testassert(TestRootRelease == 0);
215 testassert(TestRootAutorelease == 1);
216
217 [tmp release];
218 testassert(TestRootDealloc == 0);
219 testassert(TestRootRetain == 2);
220 testassert(TestRootRelease == 1);
221 testassert(TestRootAutorelease == 1);
222
223 [tmp release];
224 testassert(TestRootDealloc == 0);
225 testassert(TestRootRetain == 2);
226 testassert(TestRootRelease == 2);
227 testassert(TestRootAutorelease == 1);
228
229 } POP_POOL;
230 testassert(TestRootDealloc == 1);
231 testassert(TestRootRetain == 2);
232 testassert(TestRootRelease == 3);
233 testassert(TestRootAutorelease == 1);
234
235
236 testprintf(" Successful +1 -> +0 handshake\n");
237
238 PUSH_POOL {
239 obj = [[[TestObject alloc] init] retain];
240 testassert(obj);
241
242 TestRootRetain = 0;
243 TestRootRelease = 0;
244 TestRootAutorelease = 0;
245 TestRootDealloc = 0;
246
247 MAGIC(objc_autoreleaseReturnValue,
248 objc_unsafeClaimAutoreleasedReturnValue);
249
250 testassert(TestRootDealloc == 0);
251 testassert(TestRootRetain == 0);
252 testassert(TestRootRelease == 1);
253 testassert(TestRootAutorelease == 0);
254
255 [tmp release];
256 testassert(TestRootDealloc == 1);
257 testassert(TestRootRetain == 0);
258 testassert(TestRootRelease == 2);
259 testassert(TestRootAutorelease == 0);
260
261 } POP_POOL;
262
263 testprintf("Unsuccessful +1 -> +0 handshake\n");
264
265 PUSH_POOL {
266 obj = [[[TestObject alloc] init] retain];
267 testassert(obj);
268
269 TestRootRetain = 0;
270 TestRootRelease = 0;
271 TestRootAutorelease = 0;
272 TestRootDealloc = 0;
273
274 NOT_MAGIC(objc_autoreleaseReturnValue,
275 objc_unsafeClaimAutoreleasedReturnValue);
276
277 testassert(TestRootDealloc == 0);
278 testassert(TestRootRetain == 0);
279 testassert(TestRootRelease == 0);
280 testassert(TestRootAutorelease == 1);
281
282 [tmp release];
283 testassert(TestRootDealloc == 0);
284 testassert(TestRootRetain == 0);
285 testassert(TestRootRelease == 1);
286 testassert(TestRootAutorelease == 1);
287
288 } POP_POOL;
289 testassert(TestRootDealloc == 1);
290 testassert(TestRootRetain == 0);
291 testassert(TestRootRelease == 2);
292 testassert(TestRootAutorelease == 1);
293
294
295 testprintf(" Successful +0 -> +0 handshake\n");
296
297 PUSH_POOL {
298 obj = [[TestObject alloc] init];
299 testassert(obj);
300
301 TestRootRetain = 0;
302 TestRootRelease = 0;
303 TestRootAutorelease = 0;
304 TestRootDealloc = 0;
305
306 MAGIC(objc_retainAutoreleaseReturnValue,
307 objc_unsafeClaimAutoreleasedReturnValue);
308
309 testassert(TestRootDealloc == 0);
310 testassert(TestRootRetain == 0);
311 testassert(TestRootRelease == 0);
312 testassert(TestRootAutorelease == 0);
313
314 [tmp release];
315 testassert(TestRootDealloc == 1);
316 testassert(TestRootRetain == 0);
317 testassert(TestRootRelease == 1);
318 testassert(TestRootAutorelease == 0);
319
320 } POP_POOL;
321
322 testprintf("Unsuccessful +0 -> +0 handshake\n");
323
324 PUSH_POOL {
325 obj = [[TestObject alloc] init];
326 testassert(obj);
327
328 TestRootRetain = 0;
329 TestRootRelease = 0;
330 TestRootAutorelease = 0;
331 TestRootDealloc = 0;
332
333 NOT_MAGIC(objc_retainAutoreleaseReturnValue,
334 objc_unsafeClaimAutoreleasedReturnValue);
335
336 testassert(TestRootDealloc == 0);
337 testassert(TestRootRetain == 1);
338 testassert(TestRootRelease == 0);
339 testassert(TestRootAutorelease == 1);
340
341 [tmp release];
342 testassert(TestRootDealloc == 0);
343 testassert(TestRootRetain == 1);
344 testassert(TestRootRelease == 1);
345 testassert(TestRootAutorelease == 1);
346
347 } POP_POOL;
348 testassert(TestRootDealloc == 1);
349 testassert(TestRootRetain == 1);
350 testassert(TestRootRelease == 2);
351 testassert(TestRootAutorelease == 1);
352
353 succeed(__FILE__);
354
355 return 0;
356 }
357