rr-autorelease-fast.m 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. // TEST_CONFIG MEM=mrc
  2. // TEST_CFLAGS -Os
  3. #include "test.h"
  4. #include "testroot.i"
  5. #include <objc/objc-internal.h>
  6. #include <objc/objc-abi.h>
  7. #include <Foundation/Foundation.h>
  8. @interface TestObject : TestRoot @end
  9. @implementation TestObject @end
  10. // MAGIC and NOT_MAGIC each call two functions
  11. // with or without the magic instruction sequence, respectively.
  12. //
  13. // tmp = first(obj);
  14. // magic, or not;
  15. // tmp = second(tmp);
  16. #if __arm__
  17. #define NOT_MAGIC(first, second) \
  18. tmp = first(obj); \
  19. asm volatile("mov r8, r8"); \
  20. tmp = second(tmp);
  21. #define MAGIC(first, second) \
  22. tmp = first(obj); \
  23. asm volatile("mov r7, r7"); \
  24. tmp = second(tmp);
  25. // arm
  26. #elif __arm64__
  27. #define NOT_MAGIC(first, second) \
  28. tmp = first(obj); \
  29. asm volatile("mov x28, x28"); \
  30. tmp = second(tmp);
  31. #define MAGIC(first, second) \
  32. tmp = first(obj); \
  33. asm volatile("mov x29, x29"); \
  34. tmp = second(tmp);
  35. // arm64
  36. #elif __x86_64__
  37. #define NOT_MAGIC(first, second) \
  38. tmp = first(obj); \
  39. asm volatile("nop"); \
  40. tmp = second(tmp);
  41. #define MAGIC(first, second) \
  42. tmp = first(obj); \
  43. tmp = second(tmp);
  44. // x86_64
  45. #elif __i386__
  46. #define NOT_MAGIC(first, second) \
  47. tmp = first(obj); \
  48. tmp = second(tmp);
  49. #define MAGIC(first, second) \
  50. asm volatile("\n subl $16, %%esp" \
  51. "\n movl %[obj], (%%esp)" \
  52. "\n call _" #first \
  53. "\n" \
  54. "\n movl %%ebp, %%ebp" \
  55. "\n" \
  56. "\n movl %%eax, (%%esp)" \
  57. "\n call _" #second \
  58. "\n movl %%eax, %[tmp]" \
  59. "\n addl $16, %%esp" \
  60. : [tmp] "=r" (tmp) \
  61. : [obj] "r" (obj) \
  62. : "eax", "edx", "ecx", "cc", "memory")
  63. // i386
  64. #else
  65. #error unknown architecture
  66. #endif
  67. int
  68. main()
  69. {
  70. TestObject *tmp, *obj;
  71. #ifdef __x86_64__
  72. // need to get DYLD to resolve the stubs on x86
  73. PUSH_POOL {
  74. TestObject *warm_up = [[TestObject alloc] init];
  75. testassert(warm_up);
  76. warm_up = objc_retainAutoreleasedReturnValue(warm_up);
  77. warm_up = objc_unsafeClaimAutoreleasedReturnValue(warm_up);
  78. [warm_up release];
  79. warm_up = nil;
  80. } POP_POOL;
  81. #endif
  82. testprintf(" Successful +1 -> +1 handshake\n");
  83. PUSH_POOL {
  84. obj = [[TestObject alloc] init];
  85. testassert(obj);
  86. TestRootRetain = 0;
  87. TestRootRelease = 0;
  88. TestRootAutorelease = 0;
  89. TestRootDealloc = 0;
  90. MAGIC(objc_autoreleaseReturnValue,
  91. objc_retainAutoreleasedReturnValue);
  92. testassert(TestRootDealloc == 0);
  93. testassert(TestRootRetain == 0);
  94. testassert(TestRootRelease == 0);
  95. testassert(TestRootAutorelease == 0);
  96. [tmp release];
  97. testassert(TestRootDealloc == 1);
  98. testassert(TestRootRetain == 0);
  99. testassert(TestRootRelease == 1);
  100. testassert(TestRootAutorelease == 0);
  101. } POP_POOL;
  102. testprintf("Unsuccessful +1 -> +1 handshake\n");
  103. PUSH_POOL {
  104. obj = [[TestObject alloc] init];
  105. testassert(obj);
  106. TestRootRetain = 0;
  107. TestRootRelease = 0;
  108. TestRootAutorelease = 0;
  109. TestRootDealloc = 0;
  110. NOT_MAGIC(objc_autoreleaseReturnValue,
  111. objc_retainAutoreleasedReturnValue);
  112. testassert(TestRootDealloc == 0);
  113. testassert(TestRootRetain == 1);
  114. testassert(TestRootRelease == 0);
  115. testassert(TestRootAutorelease == 1);
  116. [tmp release];
  117. testassert(TestRootDealloc == 0);
  118. testassert(TestRootRetain == 1);
  119. testassert(TestRootRelease == 1);
  120. testassert(TestRootAutorelease == 1);
  121. } POP_POOL;
  122. testassert(TestRootDealloc == 1);
  123. testassert(TestRootRetain == 1);
  124. testassert(TestRootRelease == 2);
  125. testassert(TestRootAutorelease == 1);
  126. testprintf(" Successful +0 -> +1 handshake\n");
  127. PUSH_POOL {
  128. obj = [[TestObject alloc] init];
  129. testassert(obj);
  130. TestRootRetain = 0;
  131. TestRootRelease = 0;
  132. TestRootAutorelease = 0;
  133. TestRootDealloc = 0;
  134. MAGIC(objc_retainAutoreleaseReturnValue,
  135. objc_retainAutoreleasedReturnValue);
  136. testassert(TestRootDealloc == 0);
  137. testassert(TestRootRetain == 1);
  138. testassert(TestRootRelease == 0);
  139. testassert(TestRootAutorelease == 0);
  140. [tmp release];
  141. testassert(TestRootDealloc == 0);
  142. testassert(TestRootRetain == 1);
  143. testassert(TestRootRelease == 1);
  144. testassert(TestRootAutorelease == 0);
  145. [tmp release];
  146. testassert(TestRootDealloc == 1);
  147. testassert(TestRootRetain == 1);
  148. testassert(TestRootRelease == 2);
  149. testassert(TestRootAutorelease == 0);
  150. } POP_POOL;
  151. testprintf("Unsuccessful +0 -> +1 handshake\n");
  152. PUSH_POOL {
  153. obj = [[TestObject alloc] init];
  154. testassert(obj);
  155. TestRootRetain = 0;
  156. TestRootRelease = 0;
  157. TestRootAutorelease = 0;
  158. TestRootDealloc = 0;
  159. NOT_MAGIC(objc_retainAutoreleaseReturnValue,
  160. objc_retainAutoreleasedReturnValue);
  161. testassert(TestRootDealloc == 0);
  162. testassert(TestRootRetain == 2);
  163. testassert(TestRootRelease == 0);
  164. testassert(TestRootAutorelease == 1);
  165. [tmp release];
  166. testassert(TestRootDealloc == 0);
  167. testassert(TestRootRetain == 2);
  168. testassert(TestRootRelease == 1);
  169. testassert(TestRootAutorelease == 1);
  170. [tmp release];
  171. testassert(TestRootDealloc == 0);
  172. testassert(TestRootRetain == 2);
  173. testassert(TestRootRelease == 2);
  174. testassert(TestRootAutorelease == 1);
  175. } POP_POOL;
  176. testassert(TestRootDealloc == 1);
  177. testassert(TestRootRetain == 2);
  178. testassert(TestRootRelease == 3);
  179. testassert(TestRootAutorelease == 1);
  180. testprintf(" Successful +1 -> +0 handshake\n");
  181. PUSH_POOL {
  182. obj = [[[TestObject alloc] init] retain];
  183. testassert(obj);
  184. TestRootRetain = 0;
  185. TestRootRelease = 0;
  186. TestRootAutorelease = 0;
  187. TestRootDealloc = 0;
  188. MAGIC(objc_autoreleaseReturnValue,
  189. objc_unsafeClaimAutoreleasedReturnValue);
  190. testassert(TestRootDealloc == 0);
  191. testassert(TestRootRetain == 0);
  192. testassert(TestRootRelease == 1);
  193. testassert(TestRootAutorelease == 0);
  194. [tmp release];
  195. testassert(TestRootDealloc == 1);
  196. testassert(TestRootRetain == 0);
  197. testassert(TestRootRelease == 2);
  198. testassert(TestRootAutorelease == 0);
  199. } POP_POOL;
  200. testprintf("Unsuccessful +1 -> +0 handshake\n");
  201. PUSH_POOL {
  202. obj = [[[TestObject alloc] init] retain];
  203. testassert(obj);
  204. TestRootRetain = 0;
  205. TestRootRelease = 0;
  206. TestRootAutorelease = 0;
  207. TestRootDealloc = 0;
  208. NOT_MAGIC(objc_autoreleaseReturnValue,
  209. objc_unsafeClaimAutoreleasedReturnValue);
  210. testassert(TestRootDealloc == 0);
  211. testassert(TestRootRetain == 0);
  212. testassert(TestRootRelease == 0);
  213. testassert(TestRootAutorelease == 1);
  214. [tmp release];
  215. testassert(TestRootDealloc == 0);
  216. testassert(TestRootRetain == 0);
  217. testassert(TestRootRelease == 1);
  218. testassert(TestRootAutorelease == 1);
  219. } POP_POOL;
  220. testassert(TestRootDealloc == 1);
  221. testassert(TestRootRetain == 0);
  222. testassert(TestRootRelease == 2);
  223. testassert(TestRootAutorelease == 1);
  224. testprintf(" Successful +0 -> +0 handshake\n");
  225. PUSH_POOL {
  226. obj = [[TestObject alloc] init];
  227. testassert(obj);
  228. TestRootRetain = 0;
  229. TestRootRelease = 0;
  230. TestRootAutorelease = 0;
  231. TestRootDealloc = 0;
  232. MAGIC(objc_retainAutoreleaseReturnValue,
  233. objc_unsafeClaimAutoreleasedReturnValue);
  234. testassert(TestRootDealloc == 0);
  235. testassert(TestRootRetain == 0);
  236. testassert(TestRootRelease == 0);
  237. testassert(TestRootAutorelease == 0);
  238. [tmp release];
  239. testassert(TestRootDealloc == 1);
  240. testassert(TestRootRetain == 0);
  241. testassert(TestRootRelease == 1);
  242. testassert(TestRootAutorelease == 0);
  243. } POP_POOL;
  244. testprintf("Unsuccessful +0 -> +0 handshake\n");
  245. PUSH_POOL {
  246. obj = [[TestObject alloc] init];
  247. testassert(obj);
  248. TestRootRetain = 0;
  249. TestRootRelease = 0;
  250. TestRootAutorelease = 0;
  251. TestRootDealloc = 0;
  252. NOT_MAGIC(objc_retainAutoreleaseReturnValue,
  253. objc_unsafeClaimAutoreleasedReturnValue);
  254. testassert(TestRootDealloc == 0);
  255. testassert(TestRootRetain == 1);
  256. testassert(TestRootRelease == 0);
  257. testassert(TestRootAutorelease == 1);
  258. [tmp release];
  259. testassert(TestRootDealloc == 0);
  260. testassert(TestRootRetain == 1);
  261. testassert(TestRootRelease == 1);
  262. testassert(TestRootAutorelease == 1);
  263. } POP_POOL;
  264. testassert(TestRootDealloc == 1);
  265. testassert(TestRootRetain == 1);
  266. testassert(TestRootRelease == 2);
  267. testassert(TestRootAutorelease == 1);
  268. succeed(__FILE__);
  269. return 0;
  270. }