// TEST_CONFIG MEM=mrc /* TEST_RUN_OUTPUT objc\[\d+\]: Deallocator object 0x[0-9a-fA-F]+ overreleased while already deallocating; break on objc_overrelease_during_dealloc_error to debug OK: bigrc.m OR no overrelease enforcement OK: bigrc.m END */ #include "test.h" #include "testroot.i" static size_t LOTS; @interface Deallocator : TestRoot @end @implementation Deallocator -(void)dealloc { id o = self; size_t rc = 1; testprintf("Retain a lot during dealloc\n"); testassert(rc == 1); testassert([o retainCount] == rc); do { [o retain]; if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS); } while (++rc < LOTS); testassert([o retainCount] == rc); do { [o release]; if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS); } while (--rc > 1); testassert(rc == 1); testassert([o retainCount] == rc); testprintf("Overrelease during dealloc\n"); // Not all architectures enforce this. #if !SUPPORT_NONPOINTER_ISA testwarn("no overrelease enforcement"); fprintf(stderr, "no overrelease enforcement\n"); #endif [o release]; [super dealloc]; } @end size_t clz(uintptr_t isa) { if (sizeof(uintptr_t) == 4) return __builtin_clzl(isa); testassert(sizeof(uintptr_t) == 8); return __builtin_clzll(isa); } int main() { Deallocator *o = [Deallocator new]; size_t rc = 1; [o retain]; uintptr_t isa = *(uintptr_t *)o; if (isa & 1) { // Assume refcount in high bits. LOTS = 1 << (4 + clz(isa)); testprintf("LOTS %zu via cntlzw\n", LOTS); } else { LOTS = 0x1000000; testprintf("LOTS %zu via guess\n", LOTS); } [o release]; testprintf("Retain a lot\n"); testassert(rc == 1); testassert([o retainCount] == rc); do { [o retain]; if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS); } while (++rc < LOTS); testassert([o retainCount] == rc); do { [o release]; if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS); } while (--rc > 1); testassert(rc == 1); testassert([o retainCount] == rc); testprintf("tryRetain a lot\n"); id w; objc_storeWeak(&w, o); testassert(w == o); testassert(rc == 1); testassert([o retainCount] == rc); do { objc_loadWeakRetained(&w); if (rc % 0x100000 == 0) testprintf("%zx/%zx ++\n", rc, LOTS); } while (++rc < LOTS); testassert([o retainCount] == rc); do { [o release]; if (rc % 0x100000 == 0) testprintf("%zx/%zx --\n", rc, LOTS); } while (--rc > 1); testassert(rc == 1); testassert([o retainCount] == rc); testprintf("dealloc\n"); testassert(TestRootDealloc == 0); testassert(w != nil); [o release]; testassert(TestRootDealloc == 1); testassert(w == nil); succeed(__FILE__); }