diff options
| author | Nick Barnes | 2001-10-31 14:40:56 +0000 |
|---|---|---|
| committer | Nick Barnes | 2001-10-31 14:40:56 +0000 |
| commit | 7acfca905d76140f4cc0b09c9a12de237de364cd (patch) | |
| tree | 3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/amcsshe.c | |
| parent | b7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff) | |
| download | emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.tar.gz emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.zip | |
Branch imports for masters.
Copied from Perforce
Change: 23678
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/amcsshe.c')
| -rw-r--r-- | mps/code/amcsshe.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/mps/code/amcsshe.c b/mps/code/amcsshe.c new file mode 100644 index 00000000000..778ce7c1710 --- /dev/null +++ b/mps/code/amcsshe.c | |||
| @@ -0,0 +1,323 @@ | |||
| 1 | /* impl.c.amcsshe: POOL CLASS AMC STRESS TEST WITH HEADER | ||
| 2 | * | ||
| 3 | * $HopeName: MMsrc!amcsshe.c(trunk.4) $ | ||
| 4 | * Copyright (C) 2001 Harlequin Limited. All rights reserved. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include "fmthe.h" | ||
| 8 | #include "testlib.h" | ||
| 9 | #include "mpscamc.h" | ||
| 10 | #include "mpsavm.h" | ||
| 11 | #include "mpstd.h" | ||
| 12 | #ifdef MPS_OS_W3 | ||
| 13 | #include "mpsw3.h" | ||
| 14 | #endif | ||
| 15 | #include "mps.h" | ||
| 16 | #include <stdlib.h> | ||
| 17 | #include <string.h> | ||
| 18 | |||
| 19 | |||
| 20 | /* These values have been tuned to cause one top-generation collection. */ | ||
| 21 | #define testArenaSIZE ((size_t)1000*1024) | ||
| 22 | #define avLEN 3 | ||
| 23 | #define exactRootsCOUNT 200 | ||
| 24 | #define ambigRootsCOUNT 50 | ||
| 25 | #define bogusRootsCOUNT 4096 | ||
| 26 | #define collectionsCOUNT 37 | ||
| 27 | #define rampSIZE 9 | ||
| 28 | #define initTestFREQ 6000 | ||
| 29 | #define genCOUNT 2 | ||
| 30 | |||
| 31 | /* testChain -- generation parameters for the test */ | ||
| 32 | |||
| 33 | static mps_gen_param_s testChain[genCOUNT] = { | ||
| 34 | { 150, 0.85 }, { 170, 0.45 } }; | ||
| 35 | |||
| 36 | |||
| 37 | /* objNULL needs to be odd so that it's ignored in exactRoots. */ | ||
| 38 | #define objNULL ((mps_addr_t)0xDECEA5ED) | ||
| 39 | |||
| 40 | |||
| 41 | static mps_pool_t pool; | ||
| 42 | static mps_ap_t ap; | ||
| 43 | static mps_addr_t exactRoots[exactRootsCOUNT]; | ||
| 44 | static mps_addr_t ambigRoots[ambigRootsCOUNT]; | ||
| 45 | static mps_addr_t bogusRoots[bogusRootsCOUNT]; | ||
| 46 | |||
| 47 | |||
| 48 | |||
| 49 | static mps_word_t *ww = NULL; | ||
| 50 | static mps_word_t *tvw; | ||
| 51 | |||
| 52 | |||
| 53 | static mps_word_t dylan_make_WV(mps_word_t version, mps_word_t vb, | ||
| 54 | mps_word_t es, mps_word_t vf) | ||
| 55 | { | ||
| 56 | /* VERSION- ... VB------ reserved ES---VF- */ | ||
| 57 | return((version << (MPS_WORD_WIDTH - 8)) | | ||
| 58 | (vb << 16) | | ||
| 59 | (es << 3) | | ||
| 60 | vf); | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | static mps_res_t init(mps_addr_t addr, size_t size, | ||
| 65 | mps_addr_t *refs, size_t nr_refs) | ||
| 66 | { | ||
| 67 | |||
| 68 | /* Make sure the size is aligned. */ | ||
| 69 | if ((size & (ALIGN-1)) != 0) return MPS_RES_PARAM; | ||
| 70 | |||
| 71 | if (ww == NULL) { | ||
| 72 | ww = malloc(sizeof(mps_word_t) * (BASIC_WRAPPER_SIZE + 1)); | ||
| 73 | if (ww == NULL) return MPS_RES_MEMORY; | ||
| 74 | tvw = malloc(sizeof(mps_word_t) * BASIC_WRAPPER_SIZE); | ||
| 75 | if (tvw == NULL) { | ||
| 76 | free(ww); | ||
| 77 | return MPS_RES_MEMORY; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* Build a wrapper wrapper. */ | ||
| 81 | ww[WW] = (mps_word_t)ww; | ||
| 82 | ww[WC] = (mps_word_t)ww; /* dummy class */ | ||
| 83 | ww[WM] = (1 << 2) | 1; /* dummy subtype_mask */ | ||
| 84 | ww[WF] = ((WS - 1) << 2) | 2; | ||
| 85 | ww[WV] = dylan_make_WV(2, 0, 0, 0); | ||
| 86 | ww[WS] = (1 << 2) | 1; | ||
| 87 | ww[WP] = 1; | ||
| 88 | |||
| 89 | /* Build a wrapper for traceable vectors. */ | ||
| 90 | tvw[WW] = (mps_word_t)ww; | ||
| 91 | tvw[WC] = (mps_word_t)ww; /* dummy class */ | ||
| 92 | tvw[WM] = (1 << 2) | 1; /* dummy subtype_mask */ | ||
| 93 | tvw[WF] = 0; /* no fixed part */ | ||
| 94 | tvw[WV] = dylan_make_WV(2, 0, 0, 2); /* traceable variable part */ | ||
| 95 | tvw[WS] = 1; /* no patterns */ | ||
| 96 | } | ||
| 97 | |||
| 98 | /* If there is enough room, make a vector, otherwise just */ | ||
| 99 | /* make a padding object. */ | ||
| 100 | |||
| 101 | if (size >= sizeof(mps_word_t) * 2) { | ||
| 102 | mps_word_t *p = (mps_word_t *)addr; | ||
| 103 | mps_word_t i, t = (size / sizeof(mps_word_t)) - 2; | ||
| 104 | |||
| 105 | p[0] = (mps_word_t)tvw; /* install vector wrapper */ | ||
| 106 | p[1] = (t << 2) | 1; /* tag the vector length */ | ||
| 107 | for(i = 0; i < t; ++i) { | ||
| 108 | mps_word_t r = rnd(); | ||
| 109 | |||
| 110 | if (r & 1) | ||
| 111 | p[2+i] = ((r & ~(mps_word_t)3) | 1); /* random int */ | ||
| 112 | else | ||
| 113 | p[2+i] = (mps_word_t)refs[(r >> 1) % nr_refs]; /* random ptr */ | ||
| 114 | } | ||
| 115 | } else { | ||
| 116 | die(MPS_RES_FAIL, "small object"); | ||
| 117 | } | ||
| 118 | |||
| 119 | return MPS_RES_OK; | ||
| 120 | } | ||
| 121 | |||
| 122 | |||
| 123 | static void dylan_write(mps_addr_t addr, mps_addr_t *refs, size_t nr_refs) | ||
| 124 | { | ||
| 125 | mps_word_t *p = (mps_word_t *)addr; | ||
| 126 | mps_word_t t = p[1] >> 2; | ||
| 127 | |||
| 128 | /* If the object is a vector, update a random entry. */ | ||
| 129 | if (p[0] == (mps_word_t)tvw && t > 0) { | ||
| 130 | mps_word_t r = rnd(); | ||
| 131 | size_t i = 2 + (rnd() % t); | ||
| 132 | |||
| 133 | if (r & 1) | ||
| 134 | p[i] = ((r & ~(mps_word_t)3) | 1); /* random int */ | ||
| 135 | else | ||
| 136 | p[i] = (mps_word_t)refs[(r >> 1) % nr_refs]; /* random ptr */ | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | |||
| 141 | static mps_addr_t make(void) | ||
| 142 | { | ||
| 143 | size_t length = rnd() % (2*avLEN); | ||
| 144 | size_t size = (length+2) * sizeof(mps_word_t); | ||
| 145 | mps_addr_t p, userP; | ||
| 146 | mps_res_t res; | ||
| 147 | |||
| 148 | do { | ||
| 149 | MPS_RESERVE_BLOCK(res, p, ap, size + headerSIZE); | ||
| 150 | if (res) | ||
| 151 | die(res, "MPS_RESERVE_BLOCK"); | ||
| 152 | userP = (mps_addr_t)((char*)p + headerSIZE); | ||
| 153 | res = init(userP, size, exactRoots, exactRootsCOUNT); | ||
| 154 | if (res) | ||
| 155 | die(res, "dylan_init"); | ||
| 156 | ((int*)p)[0] = realTYPE; | ||
| 157 | ((int*)p)[1] = 0xED0ED; | ||
| 158 | } while(!mps_commit(ap, p, size + headerSIZE)); | ||
| 159 | |||
| 160 | return userP; | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | /* test -- the body of the test */ | ||
| 165 | |||
| 166 | static void *test(void *arg, size_t s) | ||
| 167 | { | ||
| 168 | mps_arena_t arena; | ||
| 169 | mps_fmt_t format; | ||
| 170 | mps_chain_t chain; | ||
| 171 | mps_root_t exactRoot, ambigRoot, bogusRoot; | ||
| 172 | unsigned long objs; size_t i; | ||
| 173 | mps_word_t collections, rampSwitch; | ||
| 174 | mps_alloc_pattern_t ramp = mps_alloc_pattern_ramp(); | ||
| 175 | int ramping; | ||
| 176 | mps_ap_t busy_ap; | ||
| 177 | mps_addr_t busy_init; | ||
| 178 | |||
| 179 | arena = (mps_arena_t)arg; | ||
| 180 | (void)s; /* unused */ | ||
| 181 | |||
| 182 | die(EnsureHeaderFormat(&format, arena), "fmt_create"); | ||
| 183 | die(mps_chain_create(&chain, arena, genCOUNT, testChain), "chain_create"); | ||
| 184 | |||
| 185 | die(mps_pool_create(&pool, arena, mps_class_amc(), format, chain), | ||
| 186 | "pool_create(amc)"); | ||
| 187 | |||
| 188 | die(mps_ap_create(&ap, pool, MPS_RANK_EXACT), "BufferCreate"); | ||
| 189 | die(mps_ap_create(&busy_ap, pool, MPS_RANK_EXACT), "BufferCreate 2"); | ||
| 190 | |||
| 191 | for(i = 0; i < exactRootsCOUNT; ++i) | ||
| 192 | exactRoots[i] = objNULL; | ||
| 193 | for(i = 0; i < ambigRootsCOUNT; ++i) | ||
| 194 | ambigRoots[i] = (mps_addr_t)rnd(); | ||
| 195 | |||
| 196 | die(mps_root_create_table_masked(&exactRoot, arena, | ||
| 197 | MPS_RANK_EXACT, (mps_rm_t)0, | ||
| 198 | &exactRoots[0], exactRootsCOUNT, | ||
| 199 | (mps_word_t)1), | ||
| 200 | "root_create_table(exact)"); | ||
| 201 | die(mps_root_create_table(&ambigRoot, arena, | ||
| 202 | MPS_RANK_AMBIG, (mps_rm_t)0, | ||
| 203 | &ambigRoots[0], ambigRootsCOUNT), | ||
| 204 | "root_create_table(ambig)"); | ||
| 205 | die(mps_root_create_table(&bogusRoot, arena, | ||
| 206 | MPS_RANK_AMBIG, (mps_rm_t)0, | ||
| 207 | &bogusRoots[0], bogusRootsCOUNT), | ||
| 208 | "root_create_table(bogus)"); | ||
| 209 | |||
| 210 | /* create an ap, and leave it busy */ | ||
| 211 | die(mps_reserve(&busy_init, busy_ap, 64), "mps_reserve busy"); | ||
| 212 | |||
| 213 | collections = 0; | ||
| 214 | rampSwitch = rampSIZE; | ||
| 215 | mps_ap_alloc_pattern_begin(ap, ramp); | ||
| 216 | mps_ap_alloc_pattern_begin(busy_ap, ramp); | ||
| 217 | ramping = 1; | ||
| 218 | objs = 0; | ||
| 219 | while(collections < collectionsCOUNT) { | ||
| 220 | unsigned long c; | ||
| 221 | size_t r; | ||
| 222 | |||
| 223 | c = mps_collections(arena); | ||
| 224 | |||
| 225 | if (collections != c) { | ||
| 226 | collections = c; | ||
| 227 | printf("\nCollection %lu, %lu objects.\n", c, objs); | ||
| 228 | for(r = 0; r < exactRootsCOUNT; ++r) { | ||
| 229 | if (exactRoots[r] != objNULL) | ||
| 230 | die(HeaderFormatCheck(exactRoots[r]), "wrapper check"); | ||
| 231 | } | ||
| 232 | if (collections == rampSwitch) { | ||
| 233 | rampSwitch += rampSIZE; | ||
| 234 | if (ramping) { | ||
| 235 | mps_ap_alloc_pattern_end(ap, ramp); | ||
| 236 | mps_ap_alloc_pattern_end(busy_ap, ramp); | ||
| 237 | /* kill half of the roots */ | ||
| 238 | for(i = 0; i < exactRootsCOUNT; i += 2) { | ||
| 239 | if (exactRoots[i] != objNULL) { | ||
| 240 | die(HeaderFormatCheck(exactRoots[i]), "ramp kill check"); | ||
| 241 | exactRoots[i] = objNULL; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | /* Every other time, switch back immediately. */ | ||
| 245 | if (collections & 1) ramping = 0; | ||
| 246 | } | ||
| 247 | if (!ramping) { | ||
| 248 | mps_ap_alloc_pattern_begin(ap, ramp); | ||
| 249 | mps_ap_alloc_pattern_begin(busy_ap, ramp); | ||
| 250 | ramping = 1; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | /* fill bogusRoots with variations of a real pointer */ | ||
| 254 | r = rnd() % exactRootsCOUNT; | ||
| 255 | if (exactRoots[i] != objNULL) { | ||
| 256 | char *p = (char*)exactRoots[i]; | ||
| 257 | |||
| 258 | for(i = 0; i < bogusRootsCOUNT; ++i, ++p) | ||
| 259 | bogusRoots[i] = (mps_addr_t)p; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | r = (size_t)rnd(); | ||
| 264 | if (r & 1) { | ||
| 265 | i = (r >> 1) % exactRootsCOUNT; | ||
| 266 | if (exactRoots[i] != objNULL) | ||
| 267 | die(HeaderFormatCheck(exactRoots[i]), "wrapper check"); | ||
| 268 | exactRoots[i] = make(); | ||
| 269 | if (exactRoots[(exactRootsCOUNT-1) - i] != objNULL) | ||
| 270 | dylan_write(exactRoots[(exactRootsCOUNT-1) - i], | ||
| 271 | exactRoots, exactRootsCOUNT); | ||
| 272 | } else { | ||
| 273 | i = (r >> 1) % ambigRootsCOUNT; | ||
| 274 | ambigRoots[(ambigRootsCOUNT-1) - i] = make(); | ||
| 275 | /* Create random interior pointers */ | ||
| 276 | ambigRoots[i] = (mps_addr_t)((char *)(ambigRoots[i/2]) + 1); | ||
| 277 | } | ||
| 278 | |||
| 279 | if (r % initTestFREQ == 0) | ||
| 280 | *(int*)busy_init = -1; /* check that the buffer is still there */ | ||
| 281 | |||
| 282 | if (objs % 1024 == 0) { | ||
| 283 | putchar('.'); | ||
| 284 | fflush(stdout); | ||
| 285 | } | ||
| 286 | |||
| 287 | ++objs; | ||
| 288 | } | ||
| 289 | |||
| 290 | (void)mps_commit(busy_ap, busy_init, 64); | ||
| 291 | mps_ap_destroy(busy_ap); | ||
| 292 | mps_ap_destroy(ap); | ||
| 293 | mps_root_destroy(exactRoot); | ||
| 294 | mps_root_destroy(ambigRoot); | ||
| 295 | mps_root_destroy(bogusRoot); | ||
| 296 | mps_pool_destroy(pool); | ||
| 297 | mps_chain_destroy(chain); | ||
| 298 | mps_fmt_destroy(format); | ||
| 299 | |||
| 300 | return NULL; | ||
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | int main(int argc, char **argv) | ||
| 305 | { | ||
| 306 | mps_arena_t arena; | ||
| 307 | mps_thr_t thread; | ||
| 308 | void *r; | ||
| 309 | |||
| 310 | randomize(argc, argv); | ||
| 311 | |||
| 312 | die(mps_arena_create(&arena, mps_arena_class_vm(), 3*testArenaSIZE), | ||
| 313 | "arena_create\n"); | ||
| 314 | die(mps_arena_commit_limit_set(arena, testArenaSIZE), "set limit"); | ||
| 315 | die(mps_thread_reg(&thread, arena), "thread_reg"); | ||
| 316 | mps_tramp(&r, test, arena, 0); | ||
| 317 | mps_thread_dereg(thread); | ||
| 318 | mps_arena_destroy(arena); | ||
| 319 | |||
| 320 | fflush(stdout); /* synchronize */ | ||
| 321 | fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); | ||
| 322 | return 0; | ||
| 323 | } | ||