mirror of
https://github.com/darlinghq/darling-objc4.git
synced 2024-11-26 21:50:26 +00:00
143 lines
3.9 KiB
Objective-C
143 lines
3.9 KiB
Objective-C
//TEST_CONFIG MEM=mrc ARCH=x86_64,ARM64,ARM64e
|
|
//TEST_ENV OBJC_DISABLE_AUTORELEASE_COALESCING=NO OBJC_DISABLE_AUTORELEASE_COALESCING_LRU=NO
|
|
|
|
#include "test.h"
|
|
#import <Foundation/NSObject.h>
|
|
#include <os/feature_private.h>
|
|
|
|
@interface Counter: NSObject {
|
|
@public
|
|
int retains;
|
|
int releases;
|
|
int autoreleases;
|
|
}
|
|
@end
|
|
@implementation Counter
|
|
|
|
- (id)retain {
|
|
retains++;
|
|
return [super retain];
|
|
}
|
|
|
|
- (oneway void)release {
|
|
releases++;
|
|
[super release];
|
|
}
|
|
|
|
- (id)autorelease {
|
|
autoreleases++;
|
|
return [super autorelease];
|
|
}
|
|
|
|
- (void)dealloc {
|
|
testprintf("%p dealloc\n", self);
|
|
[super dealloc];
|
|
}
|
|
|
|
@end
|
|
|
|
// Create a number of objects, autoreleasing each one a number of times in a
|
|
// round robin fashion. Verify that each object gets sent retain, release, and
|
|
// autorelease the correct number of times. Verify that the gap between
|
|
// autoreleasepool pointers is the given number of objects. Note: this will not
|
|
// work when the pool hits a page boundary, to be sure to stay under that limit.
|
|
void test(int objCount, int autoreleaseCount, int expectedGap) {
|
|
testprintf("Testing %d objects, %d autoreleases, expecting gap of %d\n",
|
|
objCount, autoreleaseCount, expectedGap);
|
|
|
|
Counter *objs[objCount];
|
|
for (int i = 0; i < objCount; i++)
|
|
objs[i] = [Counter new];
|
|
|
|
for (int j = 0; j < autoreleaseCount; j++)
|
|
for (int i = 0; i < objCount; i++)
|
|
[objs[i] retain];
|
|
|
|
for (int i = 0; i < objCount; i++) {
|
|
testassertequal(objs[i]->retains, autoreleaseCount);
|
|
testassertequal(objs[i]->releases, 0);
|
|
testassertequal(objs[i]->autoreleases, 0);
|
|
}
|
|
|
|
void *outer = objc_autoreleasePoolPush();
|
|
uintptr_t outerAddr = (uintptr_t)outer;
|
|
for (int j = 0; j < autoreleaseCount; j++)
|
|
for (int i = 0; i < objCount; i++)
|
|
[objs[i] autorelease];
|
|
for (int i = 0; i < objCount; i++) {
|
|
testassertequal(objs[i]->retains, autoreleaseCount);
|
|
testassertequal(objs[i]->releases, 0);
|
|
testassertequal(objs[i]->autoreleases, autoreleaseCount);
|
|
}
|
|
|
|
void *inner = objc_autoreleasePoolPush();
|
|
uintptr_t innerAddr = (uintptr_t)inner;
|
|
testprintf("outer=%p inner=%p\n", outer, inner);
|
|
// Do one more autorelease in the inner pool to make sure we correctly
|
|
// handle pool boundaries.
|
|
for (int i = 0; i < objCount; i++)
|
|
[[objs[i] retain] autorelease];
|
|
for (int i = 0; i < objCount; i++) {
|
|
testassertequal(objs[i]->retains, autoreleaseCount + 1);
|
|
testassertequal(objs[i]->releases, 0);
|
|
testassertequal(objs[i]->autoreleases, autoreleaseCount + 1);
|
|
}
|
|
|
|
objc_autoreleasePoolPop(inner);
|
|
for (int i = 0; i < objCount; i++) {
|
|
testassertequal(objs[i]->retains, autoreleaseCount + 1);
|
|
testassertequal(objs[i]->releases, 1);
|
|
testassertequal(objs[i]->autoreleases, autoreleaseCount + 1);
|
|
}
|
|
|
|
objc_autoreleasePoolPop(outer);
|
|
for (int i = 0; i < objCount; i++) {
|
|
testassertequal(objs[i]->retains, autoreleaseCount + 1);
|
|
testassertequal(objs[i]->releases, autoreleaseCount + 1);
|
|
testassertequal(objs[i]->autoreleases, autoreleaseCount + 1);
|
|
}
|
|
|
|
intptr_t gap = innerAddr - outerAddr;
|
|
testprintf("gap=%ld\n", gap);
|
|
testassertequal(gap, expectedGap * sizeof(id));
|
|
|
|
// Destroy our test objects.
|
|
for (int i = 0; i < objCount; i++)
|
|
[objs[i] release];
|
|
}
|
|
|
|
int main()
|
|
{
|
|
// Push a pool here so test() doesn't see a placeholder.
|
|
objc_autoreleasePoolPush();
|
|
|
|
test(1, 1, 2);
|
|
test(1, 2, 2);
|
|
test(1, 10, 2);
|
|
test(1, 100, 2);
|
|
test(1, 70000, 3);
|
|
|
|
test(2, 1, 3);
|
|
test(2, 2, 3);
|
|
test(2, 10, 3);
|
|
test(2, 100, 3);
|
|
test(2, 70000, 5);
|
|
|
|
test(3, 1, 4);
|
|
test(3, 2, 4);
|
|
test(3, 10, 4);
|
|
test(3, 100, 4);
|
|
test(3, 70000, 7);
|
|
|
|
test(4, 1, 5);
|
|
test(4, 2, 5);
|
|
test(4, 10, 5);
|
|
test(4, 100, 5);
|
|
test(4, 70000, 9);
|
|
|
|
test(5, 1, 6);
|
|
test(5, 2, 11);
|
|
|
|
succeed(__FILE__);
|
|
}
|