123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- // TEST_CONFIG MEM=mrc
- // TEST_CFLAGS -Os
- #include "test.h"
- #include "testroot.i"
- #include <objc/objc-internal.h>
- #include <objc/objc-abi.h>
- #include <Foundation/Foundation.h>
- @interface TestObject : TestRoot @end
- @implementation TestObject @end
- // MAGIC and NOT_MAGIC each call two functions
- // with or without the magic instruction sequence, respectively.
- //
- // tmp = first(obj);
- // magic, or not;
- // tmp = second(tmp);
- #if __arm__
- #define NOT_MAGIC(first, second) \
- tmp = first(obj); \
- asm volatile("mov r8, r8"); \
- tmp = second(tmp);
- #define MAGIC(first, second) \
- tmp = first(obj); \
- asm volatile("mov r7, r7"); \
- tmp = second(tmp);
- // arm
- #elif __arm64__
- #define NOT_MAGIC(first, second) \
- tmp = first(obj); \
- asm volatile("mov x28, x28"); \
- tmp = second(tmp);
- #define MAGIC(first, second) \
- tmp = first(obj); \
- asm volatile("mov x29, x29"); \
- tmp = second(tmp);
- // arm64
- #elif __x86_64__
- #define NOT_MAGIC(first, second) \
- tmp = first(obj); \
- asm volatile("nop"); \
- tmp = second(tmp);
- #define MAGIC(first, second) \
- tmp = first(obj); \
- tmp = second(tmp);
- // x86_64
- #elif __i386__
- #define NOT_MAGIC(first, second) \
- tmp = first(obj); \
- tmp = second(tmp);
- #define MAGIC(first, second) \
- asm volatile("\n subl $16, %%esp" \
- "\n movl %[obj], (%%esp)" \
- "\n call _" #first \
- "\n" \
- "\n movl %%ebp, %%ebp" \
- "\n" \
- "\n movl %%eax, (%%esp)" \
- "\n call _" #second \
- "\n movl %%eax, %[tmp]" \
- "\n addl $16, %%esp" \
- : [tmp] "=r" (tmp) \
- : [obj] "r" (obj) \
- : "eax", "edx", "ecx", "cc", "memory")
- // i386
- #else
- #error unknown architecture
- #endif
- int
- main()
- {
- TestObject *tmp, *obj;
-
- #ifdef __x86_64__
- // need to get DYLD to resolve the stubs on x86
- PUSH_POOL {
- TestObject *warm_up = [[TestObject alloc] init];
- testassert(warm_up);
- warm_up = objc_retainAutoreleasedReturnValue(warm_up);
- warm_up = objc_unsafeClaimAutoreleasedReturnValue(warm_up);
- [warm_up release];
- warm_up = nil;
- } POP_POOL;
- #endif
-
- testprintf(" Successful +1 -> +1 handshake\n");
-
- PUSH_POOL {
- obj = [[TestObject alloc] init];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- MAGIC(objc_autoreleaseReturnValue,
- objc_retainAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 0);
-
- [tmp release];
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 0);
- } POP_POOL;
-
- testprintf("Unsuccessful +1 -> +1 handshake\n");
-
- PUSH_POOL {
- obj = [[TestObject alloc] init];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- NOT_MAGIC(objc_autoreleaseReturnValue,
- objc_retainAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 1);
-
- [tmp release];
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 1);
- } POP_POOL;
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 2);
- testassert(TestRootAutorelease == 1);
- testprintf(" Successful +0 -> +1 handshake\n");
-
- PUSH_POOL {
- obj = [[TestObject alloc] init];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- MAGIC(objc_retainAutoreleaseReturnValue,
- objc_retainAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 0);
-
- [tmp release];
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 0);
- [tmp release];
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 2);
- testassert(TestRootAutorelease == 0);
- } POP_POOL;
-
- testprintf("Unsuccessful +0 -> +1 handshake\n");
-
- PUSH_POOL {
- obj = [[TestObject alloc] init];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- NOT_MAGIC(objc_retainAutoreleaseReturnValue,
- objc_retainAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 2);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 1);
-
- [tmp release];
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 2);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 1);
- [tmp release];
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 2);
- testassert(TestRootRelease == 2);
- testassert(TestRootAutorelease == 1);
- } POP_POOL;
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 2);
- testassert(TestRootRelease == 3);
- testassert(TestRootAutorelease == 1);
- testprintf(" Successful +1 -> +0 handshake\n");
-
- PUSH_POOL {
- obj = [[[TestObject alloc] init] retain];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- MAGIC(objc_autoreleaseReturnValue,
- objc_unsafeClaimAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 0);
-
- [tmp release];
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 2);
- testassert(TestRootAutorelease == 0);
- } POP_POOL;
- testprintf("Unsuccessful +1 -> +0 handshake\n");
-
- PUSH_POOL {
- obj = [[[TestObject alloc] init] retain];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- NOT_MAGIC(objc_autoreleaseReturnValue,
- objc_unsafeClaimAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 1);
-
- [tmp release];
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 1);
- } POP_POOL;
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 2);
- testassert(TestRootAutorelease == 1);
-
- testprintf(" Successful +0 -> +0 handshake\n");
-
- PUSH_POOL {
- obj = [[TestObject alloc] init];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- MAGIC(objc_retainAutoreleaseReturnValue,
- objc_unsafeClaimAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 0);
-
- [tmp release];
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 0);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 0);
- } POP_POOL;
- testprintf("Unsuccessful +0 -> +0 handshake\n");
-
- PUSH_POOL {
- obj = [[TestObject alloc] init];
- testassert(obj);
-
- TestRootRetain = 0;
- TestRootRelease = 0;
- TestRootAutorelease = 0;
- TestRootDealloc = 0;
- NOT_MAGIC(objc_retainAutoreleaseReturnValue,
- objc_unsafeClaimAutoreleasedReturnValue);
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 0);
- testassert(TestRootAutorelease == 1);
-
- [tmp release];
- testassert(TestRootDealloc == 0);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 1);
- testassert(TestRootAutorelease == 1);
- } POP_POOL;
- testassert(TestRootDealloc == 1);
- testassert(TestRootRetain == 1);
- testassert(TestRootRelease == 2);
- testassert(TestRootAutorelease == 1);
- succeed(__FILE__);
-
- return 0;
- }
|