]> git.saurik.com Git - apple/objc4.git/blob - test/badCache.m
objc4-779.1.tar.gz
[apple/objc4.git] / test / badCache.m
1 /*
2 TEST_CRASHES
3 TEST_RUN_OUTPUT
4 arm
5 OK: badCache.m
6 OR
7 crash now
8 objc\[\d+\]: Method cache corrupted.*
9 objc\[\d+\]: .*
10 objc\[\d+\]: .*
11 objc\[\d+\]: .*
12 objc\[\d+\]: .*
13 objc\[\d+\]: Method cache corrupted.*
14 objc\[\d+\]: HALTED
15 END
16 */
17
18
19 #include "test.h"
20
21 // Test objc_msgSend's detection of infinite loops during cache scan.
22
23 #if __arm__
24
25 int main()
26 {
27 testwarn("objc_msgSend on arm doesn't detect infinite loops");
28 fprintf(stderr, "arm\n");
29 succeed(__FILE__);
30 }
31
32 #else
33
34 #include "testroot.i"
35
36 #if __LP64__
37 typedef uint32_t mask_t;
38 #else
39 typedef uint16_t mask_t;
40 #endif
41
42 struct bucket_t {
43 uintptr_t sel;
44 uintptr_t imp;
45 };
46
47 struct cache_t {
48 uintptr_t buckets;
49 mask_t mask;
50 mask_t occupied;
51 };
52
53 struct class_t {
54 void *isa;
55 void *supercls;
56 struct cache_t cache;
57 };
58
59 @interface Subclass : TestRoot @end
60 @implementation Subclass @end
61
62 int main()
63 {
64 Class cls = [TestRoot class];
65 id obj = [cls new];
66 [obj self];
67
68 struct cache_t *cache = &((__bridge struct class_t *)cls)->cache;
69
70 // Figure out which cache mask scheme is in use by examining the existing bits.
71 int low4 = 0;
72 #if __LP64__
73 int top16 = 0;
74 #endif
75 int outlined = 0;
76
77 if (cache->buckets & 0xf) {
78 low4 = 1;
79 #if __LP64__
80 } else if ((cache->buckets & (0xffffULL << 48))) {
81 top16 = 1;
82 #endif
83 } else {
84 outlined = 1;
85 }
86
87 # define COUNT 4
88 # define COUNTSHIFT 14
89 struct bucket_t *buckets = (struct bucket_t *)calloc(sizeof(struct bucket_t), COUNT+1);
90 for (int i = 0; i < COUNT; i++) {
91 buckets[i].sel = ~0;
92 buckets[i].imp = ~0;
93 }
94 buckets[COUNT].sel = 1;
95 buckets[COUNT].imp = (uintptr_t)buckets;
96
97 if (low4) {
98 cache->buckets = (uintptr_t)buckets | COUNTSHIFT;
99 #if __LP64__
100 } else if (top16) {
101 cache->buckets = ((uintptr_t)(COUNT - 1) << 48) | (uintptr_t)buckets;
102 #endif
103 } else if (outlined) {
104 cache->mask = COUNT-1;
105 cache->buckets = (uintptr_t)buckets;
106 }
107
108 cache->occupied = 0;
109
110 fprintf(stderr, "crash now\n");
111 [obj self];
112
113 fail("should have crashed");
114 }
115
116 #endif