]>
Commit | Line | Data |
---|---|---|
7af964d1 A |
1 | #include "test.h" |
2 | #include <objc/objc.h> | |
3 | #include <objc/objc-runtime.h> | |
4 | ||
5 | @interface Super { id isa; } | |
6 | +class; | |
7 | @end | |
8 | ||
9 | @interface Sub : Super @end | |
10 | ||
11 | static int state = 0; | |
12 | ||
13 | #if defined(__ppc__) || defined(__ppc64__) | |
14 | // On ppc and ppc64, methods must be called with r12==IMP (i.e. indirect function call convention) | |
15 | #define CHECK_R12(cls) \ | |
16 | do { \ | |
17 | IMP val; \ | |
18 | __asm__ volatile ("mr %[val], r12\n" : [val] "=r" (val)); \ | |
19 | testassert(val == method_getImplementation(class_getClassMethod([cls class], _cmd))); \ | |
20 | } while (0); | |
21 | #else | |
22 | #define CHECK_R12(cls) do {/* empty */} while (0) | |
23 | #endif | |
24 | ||
25 | ||
26 | #define CHECK_ARGS(cls, sel) \ | |
27 | do { \ | |
28 | testassert(self == [cls class]); \ | |
29 | testassert(_cmd == sel_registerName(#sel "::::::::::::::::::::::::::::"));\ | |
30 | testassert(i1 == 1); \ | |
31 | testassert(i2 == 2); \ | |
32 | testassert(i3 == 3); \ | |
33 | testassert(i4 == 4); \ | |
34 | testassert(i5 == 5); \ | |
35 | testassert(i6 == 6); \ | |
36 | testassert(i7 == 7); \ | |
37 | testassert(i8 == 8); \ | |
38 | testassert(i9 == 9); \ | |
39 | testassert(i10 == 10); \ | |
40 | testassert(i11 == 11); \ | |
41 | testassert(i12 == 12); \ | |
42 | testassert(i13 == 13); \ | |
43 | testassert(f1 == 1.0); \ | |
44 | testassert(f2 == 2.0); \ | |
45 | testassert(f3 == 3.0); \ | |
46 | testassert(f4 == 4.0); \ | |
47 | testassert(f5 == 5.0); \ | |
48 | testassert(f6 == 6.0); \ | |
49 | testassert(f7 == 7.0); \ | |
50 | testassert(f8 == 8.0); \ | |
51 | testassert(f9 == 9.0); \ | |
52 | testassert(f10 == 10.0); \ | |
53 | testassert(f11 == 11.0); \ | |
54 | testassert(f12 == 12.0); \ | |
55 | testassert(f13 == 13.0); \ | |
56 | testassert(f14 == 14.0); \ | |
57 | testassert(f15 == 15.0); \ | |
58 | } while (0) | |
59 | ||
60 | struct stret { | |
61 | int a; | |
62 | int b; | |
63 | int c; | |
64 | int d; | |
65 | int e; | |
66 | int pad[32]; // force stack return on ppc64 | |
67 | }; | |
68 | ||
69 | BOOL stret_equal(struct stret a, struct stret b) | |
70 | { | |
71 | return (a.a == b.a && | |
72 | a.b == b.b && | |
73 | a.c == b.c && | |
74 | a.d == b.d && | |
75 | a.e == b.e); | |
76 | } | |
77 | ||
78 | id ID_RESULT = (id)0x12345678; | |
79 | long long LL_RESULT = __LONG_LONG_MAX__ - 2LL*__INT_MAX__; | |
80 | struct stret STRET_RESULT = {1, 2, 3, 4, 5, {0}}; | |
81 | double FP_RESULT = __DBL_MIN__ + __DBL_EPSILON__; | |
82 | long double LFP_RESULT = __LDBL_MIN__ + __LDBL_EPSILON__; | |
83 | ||
84 | ||
85 | @implementation Super | |
86 | +class { return self; } | |
87 | +(void)initialize { } | |
88 | ||
89 | +(id)idret: | |
90 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
91 | { | |
92 | CHECK_R12(Super); | |
93 | if (state == 10) CHECK_ARGS(Sub, idret); | |
94 | else CHECK_ARGS(Super, idret); | |
95 | state = 1; | |
96 | return ID_RESULT; | |
97 | } | |
98 | ||
99 | +(long long)llret: | |
100 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
101 | { | |
102 | CHECK_R12(Super); | |
103 | if (state == 10) CHECK_ARGS(Sub, llret); | |
104 | else CHECK_ARGS(Super, llret); | |
105 | state = 2; | |
106 | return LL_RESULT; | |
107 | } | |
108 | ||
109 | +(struct stret)stret: | |
110 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
111 | { | |
112 | CHECK_R12(Super); | |
113 | if (state == 10) CHECK_ARGS(Sub, stret); | |
114 | else CHECK_ARGS(Super, stret); | |
115 | state = 3; | |
116 | return STRET_RESULT; | |
117 | } | |
118 | ||
119 | +(double)fpret: | |
120 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
121 | { | |
122 | CHECK_R12(Super); | |
123 | if (state == 10) CHECK_ARGS(Sub, fpret); | |
124 | else CHECK_ARGS(Super, fpret); | |
125 | state = 4; | |
126 | return FP_RESULT; | |
127 | } | |
128 | ||
129 | +(long double)lfpret: | |
130 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
131 | { | |
132 | CHECK_R12(Super); | |
133 | if (state == 10) CHECK_ARGS(Sub, lfpret); | |
134 | else CHECK_ARGS(Super, lfpret); | |
135 | state = 5; | |
136 | return LFP_RESULT; | |
137 | } | |
138 | ||
139 | ||
140 | -(id)idret: | |
141 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
142 | { | |
143 | fail("-idret called instead of +idret"); | |
144 | CHECK_ARGS(Super, idret); | |
145 | } | |
146 | ||
147 | -(long long)llret: | |
148 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
149 | { | |
150 | fail("-llret called instead of +llret"); | |
151 | CHECK_ARGS(Super, llret); | |
152 | } | |
153 | ||
154 | -(struct stret)stret: | |
155 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
156 | { | |
157 | fail("-stret called instead of +stret"); | |
158 | CHECK_ARGS(Super, stret); | |
159 | } | |
160 | ||
161 | -(double)fpret: | |
162 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
163 | { | |
164 | fail("-fpret called instead of +fpret"); | |
165 | CHECK_ARGS(Super, fpret); | |
166 | } | |
167 | ||
168 | -(long double)lfpret: | |
169 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
170 | { | |
171 | fail("-lfpret called instead of +lfpret"); | |
172 | CHECK_ARGS(Super, lfpret); | |
173 | } | |
174 | ||
175 | @end | |
176 | ||
177 | ||
178 | @implementation Sub | |
179 | ||
180 | +(id)idret: | |
181 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
182 | { | |
183 | id result; | |
184 | CHECK_R12(Sub); | |
185 | CHECK_ARGS(Sub, idret); | |
186 | state = 10; | |
187 | result = [super idret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15]; | |
188 | testassert(state == 1); | |
189 | testassert(result == ID_RESULT); | |
190 | state = 11; | |
191 | return result; | |
192 | } | |
193 | ||
194 | +(long long)llret: | |
195 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
196 | { | |
197 | long long result; | |
198 | CHECK_R12(Sub); | |
199 | CHECK_ARGS(Sub, llret); | |
200 | state = 10; | |
201 | result = [super llret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15]; | |
202 | testassert(state == 2); | |
203 | testassert(result == LL_RESULT); | |
204 | state = 12; | |
205 | return result; | |
206 | } | |
207 | ||
208 | +(struct stret)stret: | |
209 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
210 | { | |
211 | struct stret result; | |
212 | CHECK_R12(Sub); | |
213 | CHECK_ARGS(Sub, stret); | |
214 | state = 10; | |
215 | result = [super stret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15]; | |
216 | testassert(state == 3); | |
217 | testassert(stret_equal(result, STRET_RESULT)); | |
218 | state = 13; | |
219 | return result; | |
220 | } | |
221 | ||
222 | +(double)fpret: | |
223 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
224 | { | |
225 | double result; | |
226 | CHECK_R12(Sub); | |
227 | CHECK_ARGS(Sub, fpret); | |
228 | state = 10; | |
229 | result = [super fpret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15]; | |
230 | testassert(state == 4); | |
231 | testassert(result == FP_RESULT); | |
232 | state = 14; | |
233 | return result; | |
234 | } | |
235 | ||
236 | +(long double)lfpret: | |
237 | (int)i1:(int)i2:(int)i3:(int)i4:(int)i5:(int)i6:(int)i7:(int)i8:(int)i9:(int)i10:(int)i11:(int)i12:(int)i13 :(double)f1:(double)f2:(double)f3:(double)f4:(double)f5:(double)f6:(double)f7:(double)f8:(double)f9:(double)f10:(double)f11:(double)f12:(double)f13:(double)f14:(double)f15 | |
238 | { | |
239 | long double result; | |
240 | CHECK_R12(Sub); | |
241 | CHECK_ARGS(Sub, lfpret); | |
242 | state = 10; | |
243 | result = [super lfpret:i1:i2:i3:i4:i5:i6:i7:i8:i9:i10:i11:i12:i13:f1:f2:f3:f4:f5:f6:f7:f8:f9:f10:f11:f12:f13:f14:f15]; | |
244 | testassert(state == 5); | |
245 | testassert(result == LFP_RESULT); | |
246 | state = 15; | |
247 | return result; | |
248 | } | |
249 | ||
250 | ||
251 | ||
252 | // performance-test code (do nothing for better comparability) | |
253 | ||
254 | +(id)idret_perf | |
255 | { | |
256 | return ID_RESULT; | |
257 | } | |
258 | ||
259 | +(long long)llret_perf | |
260 | { | |
261 | return LL_RESULT; | |
262 | } | |
263 | ||
264 | +(struct stret)stret_perf | |
265 | { | |
266 | return STRET_RESULT; | |
267 | } | |
268 | ||
269 | +(double)fpret_perf | |
270 | { | |
271 | return FP_RESULT; | |
272 | } | |
273 | ||
274 | +(long double)lfpret_perf | |
275 | { | |
276 | return LFP_RESULT; | |
277 | } | |
278 | @end | |
279 | ||
280 | ||
281 | int main() | |
282 | { | |
283 | int i; | |
284 | ||
285 | id idval; | |
286 | long long llval; | |
287 | struct stret stretval; | |
288 | double fpval; | |
289 | long double lfpval; | |
290 | ||
291 | uint64_t startTime; | |
292 | uint64_t totalTime; | |
293 | uint64_t targetTime; | |
294 | ||
295 | Method idmethod; | |
296 | Method llmethod; | |
297 | Method stretmethod; | |
298 | Method fpmethod; | |
299 | Method lfpmethod; | |
300 | ||
301 | id (*idfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double); | |
302 | long long (*llfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double); | |
303 | struct stret (*stretfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double); | |
304 | double (*fpfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double); | |
305 | long double (*lfpfn)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double); | |
306 | ||
307 | struct stret zero = {0, 0, 0, 0, 0, {0}}; | |
308 | ||
309 | // get +initialize out of the way | |
310 | [Sub class]; | |
311 | ||
312 | idmethod = class_getClassMethod([Super class], @selector(idret::::::::::::::::::::::::::::)); | |
313 | testassert(idmethod); | |
314 | llmethod = class_getClassMethod([Super class], @selector(llret::::::::::::::::::::::::::::)); | |
315 | testassert(llmethod); | |
316 | stretmethod = class_getClassMethod([Super class], @selector(stret::::::::::::::::::::::::::::)); | |
317 | testassert(stretmethod); | |
318 | fpmethod = class_getClassMethod([Super class], @selector(fpret::::::::::::::::::::::::::::)); | |
319 | testassert(fpmethod); | |
320 | lfpmethod = class_getClassMethod([Super class], @selector(lfpret::::::::::::::::::::::::::::)); | |
321 | testassert(lfpmethod); | |
322 | ||
323 | idfn = (id (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke; | |
324 | llfn = (long long (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke; | |
325 | stretfn = (struct stret (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke_stret; | |
326 | fpfn = (double (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke; | |
327 | lfpfn = (long double (*)(id, Method, int, int, int, int, int, int, int, int, int, int, int, int, int, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double)) method_invoke; | |
328 | ||
329 | // message uncached | |
330 | // message uncached long long | |
331 | // message uncached stret | |
332 | // message uncached fpret | |
333 | // message uncached fpret long double | |
334 | // message cached | |
335 | // message cached long long | |
336 | // message cached stret | |
337 | // message cached fpret | |
338 | // message cached fpret long double | |
339 | // fixme verify that uncached lookup didn't happen the 2nd time? | |
340 | for (i = 0; i < 5; i++) { | |
341 | state = 0; | |
342 | idval = nil; | |
343 | idval = [Sub idret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
344 | testassert(state == 11); | |
345 | testassert(idval == ID_RESULT); | |
346 | ||
347 | llval = 0; | |
348 | llval = [Sub llret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
349 | testassert(state == 12); | |
350 | testassert(llval == LL_RESULT); | |
351 | ||
352 | stretval = zero; | |
353 | stretval = [Sub stret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
354 | testassert(state == 13); | |
355 | testassert(stret_equal(stretval, STRET_RESULT)); | |
356 | ||
357 | fpval = 0; | |
358 | fpval = [Sub fpret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
359 | testassert(state == 14); | |
360 | testassert(fpval == FP_RESULT); | |
361 | ||
362 | lfpval = 0; | |
363 | lfpval = [Sub lfpret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
364 | testassert(state == 15); | |
365 | testassert(lfpval == LFP_RESULT); | |
366 | } | |
367 | ||
368 | // cached message performance | |
369 | // catches failure to cache or (abi=2) failure to fixup (#5584187) | |
370 | // fixme unless they all fail | |
371 | // `.align 4` matches loop alignment to make -O0 work | |
372 | #define COUNT 1000000 | |
373 | [Sub idret_perf]; | |
374 | startTime = mach_absolute_time(); | |
375 | asm(".align 4"); | |
376 | for (i = 0; i < COUNT; i++) { | |
377 | [Sub idret_perf]; | |
378 | } | |
379 | totalTime = mach_absolute_time() - startTime; | |
380 | testprintf("idret %llu\n", totalTime); | |
381 | targetTime = totalTime; | |
382 | ||
383 | [Sub llret_perf]; | |
384 | startTime = mach_absolute_time(); | |
385 | asm(".align 4"); | |
386 | for (i = 0; i < COUNT; i++) { | |
387 | [Sub llret_perf]; | |
388 | } | |
389 | totalTime = mach_absolute_time() - startTime; | |
390 | testprintf("llret %llu\n", totalTime); | |
391 | timeassert(totalTime > targetTime * 0.8 && totalTime < targetTime * 2.0); | |
392 | ||
393 | [Sub stret_perf]; | |
394 | startTime = mach_absolute_time(); | |
395 | asm(".align 4"); | |
396 | for (i = 0; i < COUNT; i++) { | |
397 | [Sub stret_perf]; | |
398 | } | |
399 | totalTime = mach_absolute_time() - startTime; | |
400 | testprintf("stret %llu\n", totalTime); | |
401 | timeassert(totalTime > targetTime * 0.8 && totalTime < targetTime * 5.0); | |
402 | ||
403 | [Sub fpret_perf]; | |
404 | startTime = mach_absolute_time(); | |
405 | asm(".align 4"); | |
406 | for (i = 0; i < COUNT; i++) { | |
407 | [Sub fpret_perf]; | |
408 | } | |
409 | totalTime = mach_absolute_time() - startTime; | |
410 | testprintf("fpret %llu\n", totalTime); | |
411 | timeassert(totalTime > targetTime * 0.8 && totalTime < targetTime * 2.0); | |
412 | ||
413 | [Sub lfpret_perf]; | |
414 | startTime = mach_absolute_time(); | |
415 | asm(".align 4"); | |
416 | for (i = 0; i < COUNT; i++) { | |
417 | [Sub lfpret_perf]; | |
418 | } | |
419 | totalTime = mach_absolute_time() - startTime; | |
420 | testprintf("lfpret %llu\n", totalTime); | |
421 | timeassert(totalTime > targetTime * 0.8 && totalTime < targetTime * 2.0); | |
422 | #undef COUNT | |
423 | ||
424 | // method_invoke | |
425 | // method_invoke long long | |
426 | // method_invoke_stret stret | |
427 | // method_invoke_stret fpret | |
428 | // method_invoke fpret long double | |
429 | ||
430 | state = 0; | |
431 | idval = nil; | |
432 | idval = (*idfn)([Super class], idmethod, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
433 | testassert(state == 1); | |
434 | testassert(idval == ID_RESULT); | |
435 | ||
436 | llval = 0; | |
437 | llval = (*llfn)([Super class], llmethod, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
438 | testassert(state == 2); | |
439 | testassert(llval == LL_RESULT); | |
440 | ||
441 | stretval = zero; | |
442 | stretval = (*stretfn)([Super class], stretmethod, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
443 | testassert(state == 3); | |
444 | testassert(stret_equal(stretval, STRET_RESULT)); | |
445 | ||
446 | fpval = 0; | |
447 | fpval = (*fpfn)([Super class], fpmethod, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
448 | testassert(state == 4); | |
449 | testassert(fpval == FP_RESULT); | |
450 | ||
451 | lfpval = 0; | |
452 | lfpval = (*lfpfn)([Super class], lfpmethod, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0); | |
453 | testassert(state == 5); | |
454 | testassert(lfpval == LFP_RESULT); | |
455 | ||
456 | ||
457 | // message to nil | |
458 | // message to nil long long | |
459 | // message to nil stret | |
460 | // message to nil fpret | |
461 | // message to nil fpret long double | |
462 | state = 0; | |
463 | idval = ID_RESULT; | |
464 | idval = [(id)nil idret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
465 | testassert(state == 0); | |
466 | testassert(idval == nil); | |
467 | ||
468 | state = 0; | |
469 | llval = LL_RESULT; | |
470 | llval = [(id)nil llret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
471 | testassert(state == 0); | |
472 | testassert(llval == 0LL); | |
473 | ||
474 | state = 0; | |
475 | stretval = zero; | |
476 | stretval = [(id)nil stret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
477 | testassert(state == 0); | |
478 | // no stret result guarantee | |
479 | ||
480 | state = 0; | |
481 | fpval = FP_RESULT; | |
482 | fpval = [(id)nil fpret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
483 | testassert(state == 0); | |
484 | testassert(fpval == 0.0); | |
485 | ||
486 | state = 0; | |
487 | lfpval = LFP_RESULT; | |
488 | lfpval = [(id)nil lfpret :1:2:3:4:5:6:7:8:9:10:11:12:13:1.0:2.0:3.0:4.0:5.0:6.0:7.0:8.0:9.0:10.0:11.0:12.0:13.0:14.0:15.0]; | |
489 | testassert(state == 0); | |
490 | testassert(lfpval == 0.0); | |
491 | ||
492 | ||
493 | // message forwarded | |
494 | // message forwarded long long | |
495 | // message forwarded stret | |
496 | // message forwarded fpret | |
497 | // message forwarded fpret long double | |
498 | // fixme | |
499 | ||
500 | succeed(__FILE__); | |
501 | } |