123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- // 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__);
- }
|