]> git.saurik.com Git - apple/objc4.git/blob - test/msgSend-performance.m
objc4-781.2.tar.gz
[apple/objc4.git] / test / msgSend-performance.m
1 // TEST_CONFIG
2
3 #include "test.h"
4 #include "testroot.i"
5 #include <simd/simd.h>
6
7 #if defined(__arm__)
8 // rdar://8331406
9 # define ALIGN_()
10 #else
11 # define ALIGN_() asm(".align 4");
12 #endif
13
14
15 @interface Super : TestRoot @end
16
17 @implementation Super
18
19 -(void)voidret_nop
20 {
21 return;
22 }
23
24 -(void)voidret_nop2
25 {
26 return;
27 }
28
29 -(id)idret_nop
30 {
31 return nil;
32 }
33
34 -(long long)llret_nop
35 {
36 return 0;
37 }
38
39 -(struct stret)stret_nop
40 {
41 return STRET_RESULT;
42 }
43
44 -(double)fpret_nop
45 {
46 return 0;
47 }
48
49 -(long double)lfpret_nop
50 {
51 return 0;
52 }
53
54 -(vector_ulong2)vecret_nop
55 {
56 return (vector_ulong2){0x1234567890abcdefULL, 0xfedcba0987654321ULL};
57 }
58
59 @end
60
61
62 @interface Sub : Super @end
63
64 @implementation Sub @end
65
66
67 int main()
68 {
69
70 // cached message performance
71 // catches failure to cache or (abi=2) failure to fixup (#5584187)
72 // fixme unless they all fail
73
74 uint64_t startTime;
75 uint64_t totalTime;
76 uint64_t targetTime;
77
78 Sub *sub = [Sub new];
79
80 // fill cache first
81
82 [sub voidret_nop];
83 [sub voidret_nop2];
84 [sub llret_nop];
85 [sub stret_nop];
86 [sub fpret_nop];
87 [sub lfpret_nop];
88 [sub vecret_nop];
89 [sub voidret_nop];
90 [sub voidret_nop2];
91 [sub llret_nop];
92 [sub stret_nop];
93 [sub fpret_nop];
94 [sub lfpret_nop];
95 [sub vecret_nop];
96 [sub voidret_nop];
97 [sub voidret_nop2];
98 [sub llret_nop];
99 [sub stret_nop];
100 [sub fpret_nop];
101 [sub lfpret_nop];
102 [sub vecret_nop];
103
104 // Some of these times have high variance on some compilers.
105 // The errors we're trying to catch should be catastrophically slow,
106 // so the margins here are generous to avoid false failures.
107
108 // Use voidret because id return is too slow for perf test with ARC.
109
110 // Pick smallest of voidret_nop and voidret_nop2 time
111 // in the hopes that one of them didn't collide in the method cache.
112
113 // ALIGN_ matches loop alignment to make -O0 work
114
115 #define COUNT 1000000
116
117 startTime = mach_absolute_time();
118 ALIGN_();
119 for (int i = 0; i < COUNT; i++) {
120 [sub voidret_nop];
121 }
122 totalTime = mach_absolute_time() - startTime;
123 testprintf("time: voidret %llu\n", totalTime);
124 targetTime = totalTime;
125
126 startTime = mach_absolute_time();
127 ALIGN_();
128 for (int i = 0; i < COUNT; i++) {
129 [sub voidret_nop2];
130 }
131 totalTime = mach_absolute_time() - startTime;
132 testprintf("time: voidret2 %llu\n", totalTime);
133 if (totalTime < targetTime) targetTime = totalTime;
134
135 startTime = mach_absolute_time();
136 ALIGN_();
137 for (int i = 0; i < COUNT; i++) {
138 [sub llret_nop];
139 }
140 totalTime = mach_absolute_time() - startTime;
141 timecheck("llret ", totalTime, targetTime * 0.65, targetTime * 2.0);
142
143 startTime = mach_absolute_time();
144 ALIGN_();
145 for (int i = 0; i < COUNT; i++) {
146 [sub stret_nop];
147 }
148 totalTime = mach_absolute_time() - startTime;
149 timecheck("stret ", totalTime, targetTime * 0.65, targetTime * 5.0);
150
151 startTime = mach_absolute_time();
152 ALIGN_();
153 for (int i = 0; i < COUNT; i++) {
154 [sub fpret_nop];
155 }
156 totalTime = mach_absolute_time() - startTime;
157 timecheck("fpret ", totalTime, targetTime * 0.65, targetTime * 4.0);
158
159 startTime = mach_absolute_time();
160 ALIGN_();
161 for (int i = 0; i < COUNT; i++) {
162 [sub lfpret_nop];
163 }
164 totalTime = mach_absolute_time() - startTime;
165 timecheck("lfpret", totalTime, targetTime * 0.65, targetTime * 4.0);
166
167 startTime = mach_absolute_time();
168 ALIGN_();
169 for (int i = 0; i < COUNT; i++) {
170 [sub vecret_nop];
171 }
172 totalTime = mach_absolute_time() - startTime;
173 timecheck("vecret", totalTime, targetTime * 0.65, targetTime * 4.0);
174
175 succeed(__FILE__);
176 }