bigrc.m 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // TEST_CONFIG MEM=mrc
  2. /*
  3. TEST_RUN_OUTPUT
  4. objc\[\d+\]: Deallocator object 0x[0-9a-fA-F]+ overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug
  5. OK: bigrc.m
  6. OR
  7. no overrelease enforcement
  8. OK: bigrc.m
  9. END
  10. */
  11. #include "test.h"
  12. #include "testroot.i"
  13. static size_t LOTS;
  14. @interface Deallocator : TestRoot @end
  15. @implementation Deallocator
  16. -(void)dealloc
  17. {
  18. id o = self;
  19. size_t rc = 1;
  20. testprintf("Retain a lot during dealloc\n");
  21. testassert(rc == 1);
  22. testassert([o retainCount] == rc);
  23. do {
  24. [o retain];
  25. if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
  26. } while (++rc < LOTS);
  27. testassert([o retainCount] == rc);
  28. do {
  29. [o release];
  30. if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
  31. } while (--rc > 1);
  32. testassert(rc == 1);
  33. testassert([o retainCount] == rc);
  34. testprintf("Overrelease during dealloc\n");
  35. // Not all architectures enforce this.
  36. #if !SUPPORT_NONPOINTER_ISA
  37. testwarn("no overrelease enforcement");
  38. fprintf(stderr, "no overrelease enforcement\n");
  39. #endif
  40. [o release];
  41. [super dealloc];
  42. }
  43. @end
  44. size_t clz(uintptr_t isa) {
  45. if (sizeof(uintptr_t) == 4)
  46. return __builtin_clzl(isa);
  47. testassert(sizeof(uintptr_t) == 8);
  48. return __builtin_clzll(isa);
  49. }
  50. int main()
  51. {
  52. Deallocator *o = [Deallocator new];
  53. size_t rc = 1;
  54. [o retain];
  55. uintptr_t isa = *(uintptr_t *)o;
  56. if (isa & 1) {
  57. // Assume refcount in high bits.
  58. LOTS = 1 << (4 + clz(isa));
  59. testprintf("LOTS %zu via cntlzw\n", LOTS);
  60. } else {
  61. LOTS = 0x1000000;
  62. testprintf("LOTS %zu via guess\n", LOTS);
  63. }
  64. [o release];
  65. testprintf("Retain a lot\n");
  66. testassert(rc == 1);
  67. testassert([o retainCount] == rc);
  68. do {
  69. [o retain];
  70. if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
  71. } while (++rc < LOTS);
  72. testassert([o retainCount] == rc);
  73. do {
  74. [o release];
  75. if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
  76. } while (--rc > 1);
  77. testassert(rc == 1);
  78. testassert([o retainCount] == rc);
  79. testprintf("tryRetain a lot\n");
  80. id w;
  81. objc_storeWeak(&w, o);
  82. testassert(w == o);
  83. testassert(rc == 1);
  84. testassert([o retainCount] == rc);
  85. do {
  86. objc_loadWeakRetained(&w);
  87. if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS);
  88. } while (++rc < LOTS);
  89. testassert([o retainCount] == rc);
  90. do {
  91. [o release];
  92. if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS);
  93. } while (--rc > 1);
  94. testassert(rc == 1);
  95. testassert([o retainCount] == rc);
  96. testprintf("dealloc\n");
  97. testassert(TestRootDealloc == 0);
  98. testassert(w != nil);
  99. [o release];
  100. testassert(TestRootDealloc == 1);
  101. testassert(w == nil);
  102. succeed(__FILE__);
  103. }