]> git.saurik.com Git - apple/objc4.git/blob - test/restartableRangesSynchronizeStress.m
objc4-779.1.tar.gz
[apple/objc4.git] / test / restartableRangesSynchronizeStress.m
1 // TEST_CONFIG OS=macosx,iphoneos,tvos,watchos
2
3 // This test checks that objc_msgSend's recovery path works correctly.
4 // It continuously runs msgSend on some background threads, then
5 // triggers the recovery path constantly as a stress test.
6
7 #include "test.h"
8 #include "testroot.i"
9 #include <dispatch/dispatch.h>
10
11 struct Big {
12 uintptr_t a, b, c, d, e, f, g;
13 };
14
15 @interface C1: TestRoot
16 @end
17 @implementation C1
18 - (id)idret { return nil; }
19 - (double)fpret { return 0.0; }
20 - (long double)lfpret { return 0.0; }
21 - (struct Big)stret { return (struct Big){}; }
22 @end
23
24 @interface C2: C1
25 @end
26 @implementation C2
27 - (id)idret { return [super idret]; }
28 - (double)fpret { return [super fpret]; }
29 - (long double)lfpret { return [super lfpret]; }
30 - (struct Big)stret { return [super stret]; }
31 @end
32
33 EXTERN_C kern_return_t task_restartable_ranges_synchronize(task_t task);
34
35 EXTERN_C void sendWithMsgLookup(id self, SEL _cmd);
36
37 #if defined(__arm64__) && !__has_feature(ptrauth_calls)
38 asm(
39 "_sendWithMsgLookup: \n"
40 " stp fp, lr, [sp, #-16]! \n"
41 " mov fp, sp \n"
42 " bl _objc_msgLookup \n"
43 " mov sp, fp \n"
44 " ldp fp, lr, [sp], #16 \n"
45 " br x17 \n"
46 );
47 #elif defined(__x86_64__)
48 asm(
49 "_sendWithMsgLookup: \n"
50 " pushq %rbp \n"
51 " movq %rsp, %rbp \n"
52 " callq _objc_msgLookup \n"
53 " popq %rbp \n"
54 " jmpq *%r11 \n"
55 );
56 #else
57 // Just skip it.
58 void sendWithMsgLookup(id self __unused, SEL _cmd __unused) {}
59 #endif
60
61 int main() {
62 id obj = [C2 new];
63 for(int i = 0; i < 2; i++) {
64 dispatch_async(dispatch_get_global_queue(0, 0), ^{
65 while(1) {
66 [obj idret];
67 [obj fpret];
68 [obj lfpret];
69 [obj stret];
70 sendWithMsgLookup(obj, @selector(idret));
71 }
72 });
73 }
74 for(int i = 0; i < 1000000; i++) {
75 task_restartable_ranges_synchronize(mach_task_self());;
76 }
77 succeed(__FILE__);
78 }