7 #include <objc/objc-internal.h>
8 #include <objc/objc-abi.h>
9 #include <Foundation/Foundation.h>
11 @interface TestObject : TestRoot @end
12 @implementation TestObject @end
15 // MAGIC and NOT_MAGIC each call two functions
16 // with or without the magic instruction sequence, respectively.
24 #define NOT_MAGIC(first, second) \
26 asm volatile("mov r8, r8"); \
29 #define MAGIC(first, second) \
31 asm volatile("mov r7, r7"); \
37 #define NOT_MAGIC(first, second) \
39 asm volatile("mov x28, x28"); \
42 #define MAGIC(first, second) \
44 asm volatile("mov x29, x29"); \
50 #define NOT_MAGIC(first, second) \
52 asm volatile("nop"); \
55 #define MAGIC(first, second) \
62 #define NOT_MAGIC(first, second) \
66 #define MAGIC(first, second) \
67 asm volatile("\n subl $16, %%esp" \
68 "\n movl %[obj], (%%esp)" \
71 "\n movl %%ebp, %%ebp" \
73 "\n movl %%eax, (%%esp)" \
75 "\n movl %%eax, %[tmp]" \
76 "\n addl $16, %%esp" \
79 : "eax", "edx", "ecx", "cc", "memory")
84 #error unknown architecture
92 TestObject *tmp, *obj;
95 // need to get DYLD to resolve the stubs on x86
97 TestObject *warm_up = [[TestObject alloc] init];
99 warm_up = objc_retainAutoreleasedReturnValue(warm_up);
100 warm_up = objc_unsafeClaimAutoreleasedReturnValue(warm_up);
106 testprintf(" Successful +1 -> +1 handshake\n");
109 obj = [[TestObject alloc] init];
114 TestRootAutorelease = 0;
117 MAGIC(objc_autoreleaseReturnValue,
118 objc_retainAutoreleasedReturnValue);
120 testassert(TestRootDealloc == 0);
121 testassert(TestRootRetain == 0);
122 testassert(TestRootRelease == 0);
123 testassert(TestRootAutorelease == 0);
126 testassert(TestRootDealloc == 1);
127 testassert(TestRootRetain == 0);
128 testassert(TestRootRelease == 1);
129 testassert(TestRootAutorelease == 0);
133 testprintf("Unsuccessful +1 -> +1 handshake\n");
136 obj = [[TestObject alloc] init];
141 TestRootAutorelease = 0;
144 NOT_MAGIC(objc_autoreleaseReturnValue,
145 objc_retainAutoreleasedReturnValue);
147 testassert(TestRootDealloc == 0);
148 testassert(TestRootRetain == 1);
149 testassert(TestRootRelease == 0);
150 testassert(TestRootAutorelease == 1);
153 testassert(TestRootDealloc == 0);
154 testassert(TestRootRetain == 1);
155 testassert(TestRootRelease == 1);
156 testassert(TestRootAutorelease == 1);
159 testassert(TestRootDealloc == 1);
160 testassert(TestRootRetain == 1);
161 testassert(TestRootRelease == 2);
162 testassert(TestRootAutorelease == 1);
165 testprintf(" Successful +0 -> +1 handshake\n");
168 obj = [[TestObject alloc] init];
173 TestRootAutorelease = 0;
176 MAGIC(objc_retainAutoreleaseReturnValue,
177 objc_retainAutoreleasedReturnValue);
179 testassert(TestRootDealloc == 0);
180 testassert(TestRootRetain == 1);
181 testassert(TestRootRelease == 0);
182 testassert(TestRootAutorelease == 0);
185 testassert(TestRootDealloc == 0);
186 testassert(TestRootRetain == 1);
187 testassert(TestRootRelease == 1);
188 testassert(TestRootAutorelease == 0);
191 testassert(TestRootDealloc == 1);
192 testassert(TestRootRetain == 1);
193 testassert(TestRootRelease == 2);
194 testassert(TestRootAutorelease == 0);
198 testprintf("Unsuccessful +0 -> +1 handshake\n");
201 obj = [[TestObject alloc] init];
206 TestRootAutorelease = 0;
209 NOT_MAGIC(objc_retainAutoreleaseReturnValue,
210 objc_retainAutoreleasedReturnValue);
212 testassert(TestRootDealloc == 0);
213 testassert(TestRootRetain == 2);
214 testassert(TestRootRelease == 0);
215 testassert(TestRootAutorelease == 1);
218 testassert(TestRootDealloc == 0);
219 testassert(TestRootRetain == 2);
220 testassert(TestRootRelease == 1);
221 testassert(TestRootAutorelease == 1);
224 testassert(TestRootDealloc == 0);
225 testassert(TestRootRetain == 2);
226 testassert(TestRootRelease == 2);
227 testassert(TestRootAutorelease == 1);
230 testassert(TestRootDealloc == 1);
231 testassert(TestRootRetain == 2);
232 testassert(TestRootRelease == 3);
233 testassert(TestRootAutorelease == 1);
236 testprintf(" Successful +1 -> +0 handshake\n");
239 obj = [[[TestObject alloc] init] retain];
244 TestRootAutorelease = 0;
247 MAGIC(objc_autoreleaseReturnValue,
248 objc_unsafeClaimAutoreleasedReturnValue);
250 testassert(TestRootDealloc == 0);
251 testassert(TestRootRetain == 0);
252 testassert(TestRootRelease == 1);
253 testassert(TestRootAutorelease == 0);
256 testassert(TestRootDealloc == 1);
257 testassert(TestRootRetain == 0);
258 testassert(TestRootRelease == 2);
259 testassert(TestRootAutorelease == 0);
263 testprintf("Unsuccessful +1 -> +0 handshake\n");
266 obj = [[[TestObject alloc] init] retain];
271 TestRootAutorelease = 0;
274 NOT_MAGIC(objc_autoreleaseReturnValue,
275 objc_unsafeClaimAutoreleasedReturnValue);
277 testassert(TestRootDealloc == 0);
278 testassert(TestRootRetain == 0);
279 testassert(TestRootRelease == 0);
280 testassert(TestRootAutorelease == 1);
283 testassert(TestRootDealloc == 0);
284 testassert(TestRootRetain == 0);
285 testassert(TestRootRelease == 1);
286 testassert(TestRootAutorelease == 1);
289 testassert(TestRootDealloc == 1);
290 testassert(TestRootRetain == 0);
291 testassert(TestRootRelease == 2);
292 testassert(TestRootAutorelease == 1);
295 testprintf(" Successful +0 -> +0 handshake\n");
298 obj = [[TestObject alloc] init];
303 TestRootAutorelease = 0;
306 MAGIC(objc_retainAutoreleaseReturnValue,
307 objc_unsafeClaimAutoreleasedReturnValue);
309 testassert(TestRootDealloc == 0);
310 testassert(TestRootRetain == 0);
311 testassert(TestRootRelease == 0);
312 testassert(TestRootAutorelease == 0);
315 testassert(TestRootDealloc == 1);
316 testassert(TestRootRetain == 0);
317 testassert(TestRootRelease == 1);
318 testassert(TestRootAutorelease == 0);
322 testprintf("Unsuccessful +0 -> +0 handshake\n");
325 obj = [[TestObject alloc] init];
330 TestRootAutorelease = 0;
333 NOT_MAGIC(objc_retainAutoreleaseReturnValue,
334 objc_unsafeClaimAutoreleasedReturnValue);
336 testassert(TestRootDealloc == 0);
337 testassert(TestRootRetain == 1);
338 testassert(TestRootRelease == 0);
339 testassert(TestRootAutorelease == 1);
342 testassert(TestRootDealloc == 0);
343 testassert(TestRootRetain == 1);
344 testassert(TestRootRelease == 1);
345 testassert(TestRootAutorelease == 1);
348 testassert(TestRootDealloc == 1);
349 testassert(TestRootRetain == 1);
350 testassert(TestRootRelease == 2);
351 testassert(TestRootAutorelease == 1);