diff options
| author | Nick Barnes | 2002-04-11 15:10:37 +0100 |
|---|---|---|
| committer | Nick Barnes | 2002-04-11 15:10:37 +0100 |
| commit | c3a928aa1ea5499f2a8bcf708d413f2baf56f772 (patch) | |
| tree | 37e36614a8615923ec8c35e4b61cb54e5520e3d0 /mps/code | |
| parent | 5da4c1e316636ee7218ca97bac693a06784808b7 (diff) | |
| download | emacs-c3a928aa1ea5499f2a8bcf708d413f2baf56f772.tar.gz emacs-c3a928aa1ea5499f2a8bcf708d413f2baf56f772.zip | |
Make awl (and lo) work with auto-header formats.
New test awluthe, based on awlut, using auto-header format in AWL
and LO. Seems to work. Not the greatest test ever.
Copied from Perforce
Change: 28076
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/awluthe.c | 326 | ||||
| -rw-r--r-- | mps/code/comm.gmk | 12 | ||||
| -rw-r--r-- | mps/code/fmthe.c | 218 | ||||
| -rw-r--r-- | mps/code/fmthe.h | 6 | ||||
| -rw-r--r-- | mps/code/fri4gc.gmk | 4 | ||||
| -rw-r--r-- | mps/code/poolawl.c | 54 | ||||
| -rw-r--r-- | mps/code/poollo.c | 43 |
7 files changed, 631 insertions, 32 deletions
diff --git a/mps/code/awluthe.c b/mps/code/awluthe.c new file mode 100644 index 00000000000..cb3fe99f343 --- /dev/null +++ b/mps/code/awluthe.c | |||
| @@ -0,0 +1,326 @@ | |||
| 1 | /* impl.c.awluthe: POOL CLASS AWL UNIT TEST WITH OBJECT HEADERS | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * Copyright (c) 2001 Ravenbrook Limited. | ||
| 5 | * | ||
| 6 | * DESIGN | ||
| 7 | * | ||
| 8 | * .design: see design.mps.poolawl.test.* | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include "mpscawl.h" | ||
| 12 | #include "mpsclo.h" | ||
| 13 | #include "mpsavm.h" | ||
| 14 | #include "fmthe.h" | ||
| 15 | #include "testlib.h" | ||
| 16 | #include "mps.h" | ||
| 17 | #include "mpstd.h" | ||
| 18 | #ifdef MPS_OS_W3 | ||
| 19 | #include "mpsw3.h" | ||
| 20 | #endif | ||
| 21 | #include <string.h> | ||
| 22 | |||
| 23 | |||
| 24 | #define testArenaSIZE ((size_t)64<<20) | ||
| 25 | #define TABLE_SLOTS 49 | ||
| 26 | #define ITERATIONS 5000 | ||
| 27 | #define CHATTER 100 | ||
| 28 | |||
| 29 | |||
| 30 | static mps_word_t bogus_class; | ||
| 31 | |||
| 32 | #define UNINIT 0x041412ED | ||
| 33 | |||
| 34 | #define DYLAN_ALIGN 4 /* depends on value defined in fmtdy.c */ | ||
| 35 | |||
| 36 | |||
| 37 | /* size_tAlignUp -- align w up to alignment a */ | ||
| 38 | |||
| 39 | #define size_tAlignUp(w, a) (((w) + (a) - 1) & ~((size_t)(a) - 1)) | ||
| 40 | |||
| 41 | |||
| 42 | static mps_word_t wrapper_wrapper[] = { | ||
| 43 | UNINIT, /* wrapper */ | ||
| 44 | UNINIT, /* class */ | ||
| 45 | 0, /* Extra word */ | ||
| 46 | 4uL<<2|2, /* F */ | ||
| 47 | 2uL<<(MPS_WORD_WIDTH - 8), /* V */ | ||
| 48 | 1uL<<2|1, /* VL */ | ||
| 49 | 1 /* patterns */ | ||
| 50 | }; | ||
| 51 | |||
| 52 | |||
| 53 | static mps_word_t string_wrapper[] = { | ||
| 54 | UNINIT, /* wrapper */ | ||
| 55 | UNINIT, /* class */ | ||
| 56 | 0, /* extra word */ | ||
| 57 | 0, /* F */ | ||
| 58 | 2uL<<(MPS_WORD_WIDTH - 8)|3uL<<3|4, /* V */ | ||
| 59 | 1 /* VL */ | ||
| 60 | }; | ||
| 61 | |||
| 62 | static mps_word_t table_wrapper[] = { | ||
| 63 | UNINIT, /* wrapper */ | ||
| 64 | UNINIT, /* class */ | ||
| 65 | 0, /* extra word */ | ||
| 66 | 1uL<<2|1, /* F */ | ||
| 67 | 2uL<<(MPS_WORD_WIDTH - 8)|2, /* V */ | ||
| 68 | 1 /* VL */ | ||
| 69 | }; | ||
| 70 | |||
| 71 | |||
| 72 | static void initialise_wrapper(mps_word_t *wrapper) | ||
| 73 | { | ||
| 74 | wrapper[0] = (mps_word_t)&wrapper_wrapper; | ||
| 75 | wrapper[1] = (mps_word_t)&bogus_class; | ||
| 76 | } | ||
| 77 | |||
| 78 | |||
| 79 | /* alloc_string - create a dylan string object | ||
| 80 | * | ||
| 81 | * create a dylan string object (byte vector) whose contents | ||
| 82 | * are the string s (including the terminating NUL) | ||
| 83 | * .assume.dylan-obj | ||
| 84 | */ | ||
| 85 | |||
| 86 | static mps_word_t *alloc_string(char *s, mps_ap_t ap) | ||
| 87 | { | ||
| 88 | size_t l; | ||
| 89 | size_t objsize; | ||
| 90 | void *p; | ||
| 91 | mps_word_t *object; | ||
| 92 | |||
| 93 | l = strlen(s)+1; | ||
| 94 | /* number of words * sizeof word */ | ||
| 95 | objsize = (2 + (l+sizeof(mps_word_t)-1)/sizeof(mps_word_t)) | ||
| 96 | * sizeof(mps_word_t); | ||
| 97 | objsize = size_tAlignUp(objsize, DYLAN_ALIGN); | ||
| 98 | do { | ||
| 99 | size_t i; | ||
| 100 | char *s2; | ||
| 101 | |||
| 102 | die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Leaf\n"); | ||
| 103 | object = (mps_word_t *)((char *)p + headerSIZE); | ||
| 104 | object[0] = (mps_word_t)string_wrapper; | ||
| 105 | object[1] = l << 2 | 1; | ||
| 106 | s2 = (char *)&object[2]; | ||
| 107 | for(i = 0; i < l; ++i) { | ||
| 108 | s2[i] = s[i]; | ||
| 109 | } | ||
| 110 | ((int*)p)[0] = realHeader; | ||
| 111 | ((int*)p)[1] = 0xED0ED; | ||
| 112 | } while(!mps_commit(ap, p, objsize + headerSIZE)); | ||
| 113 | return object; | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | /* alloc_table -- create a table with n variable slots | ||
| 118 | * | ||
| 119 | * .assume.dylan-obj | ||
| 120 | */ | ||
| 121 | |||
| 122 | static mps_word_t *alloc_table(unsigned long n, mps_ap_t ap) | ||
| 123 | { | ||
| 124 | size_t objsize; | ||
| 125 | void *p; | ||
| 126 | mps_word_t *object; | ||
| 127 | |||
| 128 | objsize = (3 + n) * sizeof(mps_word_t); | ||
| 129 | objsize = size_tAlignUp(objsize, MPS_PF_ALIGN); | ||
| 130 | do { | ||
| 131 | unsigned long i; | ||
| 132 | |||
| 133 | die(mps_reserve(&p, ap, objsize + headerSIZE), "Reserve Table\n"); | ||
| 134 | object = (mps_word_t *)((char *)p + headerSIZE); | ||
| 135 | object[0] = (mps_word_t)table_wrapper; | ||
| 136 | object[1] = 0; | ||
| 137 | object[2] = n << 2 | 1; | ||
| 138 | for(i = 0; i < n; ++i) { | ||
| 139 | object[3+i] = 0; | ||
| 140 | } | ||
| 141 | ((int*)p)[0] = realHeader; | ||
| 142 | ((int*)p)[1] = 0xED0ED; | ||
| 143 | } while(!mps_commit(ap, p, objsize + headerSIZE)); | ||
| 144 | return object; | ||
| 145 | } | ||
| 146 | |||
| 147 | |||
| 148 | /* gets the nth slot from a table | ||
| 149 | * .assume.dylan-obj | ||
| 150 | */ | ||
| 151 | static mps_word_t *table_slot(mps_word_t *table, unsigned long n) | ||
| 152 | { | ||
| 153 | return (mps_word_t *)table[3+n]; | ||
| 154 | } | ||
| 155 | |||
| 156 | |||
| 157 | /* sets the nth slot in a table | ||
| 158 | * .assume.dylan-obj | ||
| 159 | */ | ||
| 160 | static void set_table_slot(mps_word_t *table, | ||
| 161 | unsigned long n, mps_word_t *p) | ||
| 162 | { | ||
| 163 | cdie(table[0] == (mps_word_t)table_wrapper, "set_table_slot"); | ||
| 164 | table[3+n] = (mps_word_t)p; | ||
| 165 | } | ||
| 166 | |||
| 167 | |||
| 168 | /* links two tables together via their link slot | ||
| 169 | * (1st fixed part slot) | ||
| 170 | */ | ||
| 171 | static void table_link(mps_word_t *t1, mps_word_t *t2) | ||
| 172 | { | ||
| 173 | cdie(t1[0] == (mps_word_t)table_wrapper, "table_link 1"); | ||
| 174 | cdie(t2[0] == (mps_word_t)table_wrapper, "table_link 2"); | ||
| 175 | t1[1] = (mps_word_t)t2; | ||
| 176 | t2[1] = (mps_word_t)t1; | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | static void test(mps_ap_t leafap, mps_ap_t exactap, mps_ap_t weakap, | ||
| 181 | mps_ap_t bogusap) | ||
| 182 | { | ||
| 183 | mps_word_t *weaktable; | ||
| 184 | mps_word_t *exacttable; | ||
| 185 | mps_word_t *preserve[TABLE_SLOTS]; /* preserves objects in the weak */ | ||
| 186 | /* table by referring to them */ | ||
| 187 | unsigned long i, j; | ||
| 188 | void *p; | ||
| 189 | |||
| 190 | exacttable = alloc_table(TABLE_SLOTS, exactap); | ||
| 191 | weaktable = alloc_table(TABLE_SLOTS, weakap); | ||
| 192 | table_link(exacttable, weaktable); | ||
| 193 | |||
| 194 | /* Leave bogusap between reserve and commit for the duration */ | ||
| 195 | die(mps_reserve(&p, bogusap, 64), "Reserve bogus"); | ||
| 196 | |||
| 197 | for(i = 0; i < TABLE_SLOTS; ++i) { | ||
| 198 | mps_word_t *string; | ||
| 199 | if (rnd() % 2 == 0) { | ||
| 200 | string = alloc_string("iamalive", leafap); | ||
| 201 | preserve[i] = string; | ||
| 202 | } else { | ||
| 203 | string = alloc_string("iamdead", leafap); | ||
| 204 | preserve[i] = 0; | ||
| 205 | } | ||
| 206 | set_table_slot(weaktable, i, string); | ||
| 207 | string = alloc_string("iamexact", leafap); | ||
| 208 | set_table_slot(exacttable, i, string); | ||
| 209 | } | ||
| 210 | |||
| 211 | for(j = 0; j < ITERATIONS; ++j) { | ||
| 212 | for(i = 0; i < TABLE_SLOTS; ++i) { | ||
| 213 | mps_word_t *string; | ||
| 214 | |||
| 215 | string = alloc_string("spong", leafap); | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | for(i = 0; i < TABLE_SLOTS; ++i) { | ||
| 220 | if (preserve[i] == 0) { | ||
| 221 | if (table_slot(weaktable, i)) { | ||
| 222 | error("Strongly unreachable weak table entry found, slot %lu.\n", i); | ||
| 223 | } else { | ||
| 224 | if (table_slot(exacttable, i) != 0) { | ||
| 225 | error("Weak table entry deleted, but corresponding " | ||
| 226 | "exact table entry not deleted, slot %lu.\n", i); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | (void)mps_commit(bogusap, p, 64); | ||
| 233 | } | ||
| 234 | |||
| 235 | |||
| 236 | /* setup -- set up pools for the test | ||
| 237 | * | ||
| 238 | * v serves two purposes: | ||
| 239 | * - a pseudo stack base for the stack root. | ||
| 240 | * - pointer to a guff structure, which packages some values needed | ||
| 241 | * (arena and thr mostly) | ||
| 242 | */ | ||
| 243 | |||
| 244 | struct guff_s { | ||
| 245 | mps_arena_t arena; | ||
| 246 | mps_thr_t thr; | ||
| 247 | }; | ||
| 248 | |||
| 249 | static void *setup(void *v, size_t s) | ||
| 250 | { | ||
| 251 | struct guff_s *guff; | ||
| 252 | mps_arena_t arena; | ||
| 253 | mps_pool_t leafpool; | ||
| 254 | mps_pool_t tablepool; | ||
| 255 | mps_fmt_t dylanfmt; | ||
| 256 | mps_fmt_t dylanweakfmt; | ||
| 257 | mps_ap_t leafap, exactap, weakap, bogusap; | ||
| 258 | mps_root_t stack; | ||
| 259 | mps_thr_t thr; | ||
| 260 | |||
| 261 | guff = (struct guff_s *)v; | ||
| 262 | (void)s; | ||
| 263 | arena = guff->arena; | ||
| 264 | thr = guff->thr; | ||
| 265 | |||
| 266 | die(mps_root_create_reg(&stack, arena, MPS_RANK_AMBIG, 0, thr, | ||
| 267 | mps_stack_scan_ambig, v, 0), | ||
| 268 | "Root Create\n"); | ||
| 269 | EnsureHeaderFormat(&dylanfmt, arena); | ||
| 270 | EnsureHeaderWeakFormat(&dylanweakfmt, arena); | ||
| 271 | die(mps_pool_create(&leafpool, arena, mps_class_lo(), dylanfmt), | ||
| 272 | "Leaf Pool Create\n"); | ||
| 273 | die(mps_pool_create(&tablepool, arena, mps_class_awl(), dylanweakfmt, | ||
| 274 | dylan_weak_dependent), | ||
| 275 | "Table Pool Create\n"); | ||
| 276 | die(mps_ap_create(&leafap, leafpool, MPS_RANK_EXACT), | ||
| 277 | "Leaf AP Create\n"); | ||
| 278 | die(mps_ap_create(&exactap, tablepool, MPS_RANK_EXACT), | ||
| 279 | "Exact AP Create\n"); | ||
| 280 | die(mps_ap_create(&weakap, tablepool, MPS_RANK_WEAK), | ||
| 281 | "Weak AP Create\n"); | ||
| 282 | die(mps_ap_create(&bogusap, tablepool, MPS_RANK_EXACT), | ||
| 283 | "Bogus AP Create\n"); | ||
| 284 | |||
| 285 | test(leafap, exactap, weakap, bogusap); | ||
| 286 | |||
| 287 | mps_ap_destroy(bogusap); | ||
| 288 | mps_ap_destroy(weakap); | ||
| 289 | mps_ap_destroy(exactap); | ||
| 290 | mps_ap_destroy(leafap); | ||
| 291 | mps_pool_destroy(tablepool); | ||
| 292 | mps_pool_destroy(leafpool); | ||
| 293 | mps_fmt_destroy(dylanweakfmt); | ||
| 294 | mps_fmt_destroy(dylanfmt); | ||
| 295 | mps_root_destroy(stack); | ||
| 296 | |||
| 297 | return NULL; | ||
| 298 | } | ||
| 299 | |||
| 300 | |||
| 301 | int main(int argc, char **argv) | ||
| 302 | { | ||
| 303 | struct guff_s guff; | ||
| 304 | mps_arena_t arena; | ||
| 305 | mps_thr_t thread; | ||
| 306 | void *r; | ||
| 307 | |||
| 308 | randomize(argc, argv); | ||
| 309 | |||
| 310 | initialise_wrapper(wrapper_wrapper); | ||
| 311 | initialise_wrapper(string_wrapper); | ||
| 312 | initialise_wrapper(table_wrapper); | ||
| 313 | |||
| 314 | die(mps_arena_create(&arena, mps_arena_class_vm(), testArenaSIZE), | ||
| 315 | "arena_create\n"); | ||
| 316 | die(mps_thread_reg(&thread, arena), "thread_reg"); | ||
| 317 | guff.arena = arena; | ||
| 318 | guff.thr = thread; | ||
| 319 | mps_tramp(&r, setup, &guff, 0); | ||
| 320 | mps_thread_dereg(thread); | ||
| 321 | mps_arena_destroy(arena); | ||
| 322 | |||
| 323 | fflush(stdout); /* synchronize */ | ||
| 324 | fprintf(stderr, "\nConclusion: Failed to find any defects.\n"); | ||
| 325 | return 0; | ||
| 326 | } | ||
diff --git a/mps/code/comm.gmk b/mps/code/comm.gmk index aafb2134680..8e3172f7c77 100644 --- a/mps/code/comm.gmk +++ b/mps/code/comm.gmk | |||
| @@ -277,7 +277,7 @@ endif | |||
| 277 | # %%TARGET: Add the target to the all dependencies, if it uses the | 277 | # %%TARGET: Add the target to the all dependencies, if it uses the |
| 278 | # CONFIG_PROD_MPS configuration, to swall if CONFIG_PROD_EPCORE | 278 | # CONFIG_PROD_MPS configuration, to swall if CONFIG_PROD_EPCORE |
| 279 | 279 | ||
| 280 | all: mpmss sacss amcss amcsshe amsss segsmss awlut \ | 280 | all: mpmss sacss amcss amcsshe amsss segsmss awlut awluthe \ |
| 281 | mpsicv lockcov poolncv locv qs apss \ | 281 | mpsicv lockcov poolncv locv qs apss \ |
| 282 | finalcv arenacv bttest teletest \ | 282 | finalcv arenacv bttest teletest \ |
| 283 | abqtest cbstest btcv mv2test messtest \ | 283 | abqtest cbstest btcv mv2test messtest \ |
| @@ -289,8 +289,9 @@ swall: mmsw.a epvmss replaysw epdss | |||
| 289 | # These tests are run overnight (see design.buildsys.overnight). | 289 | # These tests are run overnight (see design.buildsys.overnight). |
| 290 | # bttest & teletest cannot be run unattended | 290 | # bttest & teletest cannot be run unattended |
| 291 | # mv2test cannot be run because MV2 is broken | 291 | # mv2test cannot be run because MV2 is broken |
| 292 | testrun: mpmss apss sacss amcss amcsshe amsss segsmss awlut mpsicv lockcov \ | 292 | testrun: mpmss apss sacss amcss amcsshe amsss segsmss awlut awluthe \ |
| 293 | poolncv locv qs finalcv arenacv abqtest cbstest btcv messtest | 293 | mpsicv lockcov poolncv locv qs finalcv arenacv \ |
| 294 | abqtest cbstest btcv messtest | ||
| 294 | $(^:%=date && $(PFM)/$(VARIETY)/% &&) true | 295 | $(^:%=date && $(PFM)/$(VARIETY)/% &&) true |
| 295 | 296 | ||
| 296 | # Runs the automatic tests that are built with CONFIG_PROD_EPCORE | 297 | # Runs the automatic tests that are built with CONFIG_PROD_EPCORE |
| @@ -304,7 +305,7 @@ testrunep: epvmss epdss | |||
| 304 | # %%TARGET: Add a pseudo-target for the new target here. | 305 | # %%TARGET: Add a pseudo-target for the new target here. |
| 305 | 306 | ||
| 306 | mpmss sacss amcss amcssth amcsshe amsss segsmss awlut awlutth \ | 307 | mpmss sacss amcss amcssth amcsshe amsss segsmss awlut awlutth \ |
| 307 | mpsicv lockcov poolncv locv qs apss \ | 308 | awluthe mpsicv lockcov poolncv locv qs apss \ |
| 308 | finalcv arenacv bttest teletest epvmss epdss \ | 309 | finalcv arenacv bttest teletest epvmss epdss \ |
| 309 | abqtest cbstest btcv mv2test \ | 310 | abqtest cbstest btcv mv2test \ |
| 310 | messtest \ | 311 | messtest \ |
| @@ -409,6 +410,9 @@ $(PFM)/$(VARIETY)/epdss: $(PFM)/$(VARIETY)/epdss.o \ | |||
| 409 | $(PFM)/$(VARIETY)/awlut: $(PFM)/$(VARIETY)/awlut.o \ | 410 | $(PFM)/$(VARIETY)/awlut: $(PFM)/$(VARIETY)/awlut.o \ |
| 410 | $(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ) | 411 | $(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ) |
| 411 | 412 | ||
| 413 | $(PFM)/$(VARIETY)/awluthe: $(PFM)/$(VARIETY)/awluthe.o \ | ||
| 414 | $(PFM)/$(VARIETY)/fmthe.o $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ) | ||
| 415 | |||
| 412 | $(PFM)/$(VARIETY)/awlutth: $(PFM)/$(VARIETY)/awlutth.o \ | 416 | $(PFM)/$(VARIETY)/awlutth: $(PFM)/$(VARIETY)/awlutth.o \ |
| 413 | $(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ) | 417 | $(FMTDYTSTOBJ) $(MPMOBJ) $(LOOBJ) $(AWLOBJ) $(TESTLIBOBJ) |
| 414 | 418 | ||
diff --git a/mps/code/fmthe.c b/mps/code/fmthe.c index 9657c056a80..ffd9a29a4c7 100644 --- a/mps/code/fmthe.c +++ b/mps/code/fmthe.c | |||
| @@ -159,7 +159,7 @@ static int dylan_wrapper_check(mps_word_t *w) | |||
| 159 | /* size. This assumes that DylanWorks is only going to use byte */ | 159 | /* size. This assumes that DylanWorks is only going to use byte */ |
| 160 | /* vectors in the non-word case. */ | 160 | /* vectors in the non-word case. */ |
| 161 | 161 | ||
| 162 | /* Variable part format 6 is reserved. */ | 162 | /* Variable part format 6 is reserved. */ |
| 163 | assert(vf != 6); | 163 | assert(vf != 6); |
| 164 | 164 | ||
| 165 | /* There should be no shift in word vector formats. */ | 165 | /* There should be no shift in word vector formats. */ |
| @@ -216,6 +216,79 @@ static mps_res_t dylan_scan_contig(mps_ss_t mps_ss, | |||
| 216 | return MPS_RES_OK; | 216 | return MPS_RES_OK; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | /* dylan_weak_dependent -- returns the linked object, if any. | ||
| 220 | */ | ||
| 221 | |||
| 222 | extern mps_addr_t dylan_weak_dependent(mps_addr_t parent) | ||
| 223 | { | ||
| 224 | mps_word_t *object; | ||
| 225 | mps_word_t *wrapper; | ||
| 226 | mps_word_t fword; | ||
| 227 | mps_word_t fl; | ||
| 228 | mps_word_t ff; | ||
| 229 | |||
| 230 | assert(parent != NULL); | ||
| 231 | object = (mps_word_t *)parent; | ||
| 232 | wrapper = (mps_word_t *)object[0]; | ||
| 233 | assert(dylan_wrapper_check(wrapper)); | ||
| 234 | fword = wrapper[3]; | ||
| 235 | ff = fword & 3; | ||
| 236 | /* traceable fixed part */ | ||
| 237 | assert(ff == 1); | ||
| 238 | fl = fword & ~3uL; | ||
| 239 | /* at least one fixed field */ | ||
| 240 | assert(fl >= 1); | ||
| 241 | return (mps_addr_t) object[1]; | ||
| 242 | } | ||
| 243 | |||
| 244 | |||
| 245 | /* Scan weakly a contiguous array of references in [base, limit). */ | ||
| 246 | /* Only required to scan vectors for Dylan Weak Tables. */ | ||
| 247 | /* Depends on the vector length field being scannable (ie a tagged */ | ||
| 248 | /* integer). */ | ||
| 249 | /* When a reference that has been fixed to NULL is detected the */ | ||
| 250 | /* corresponding reference in the associated table (pointed to be the */ | ||
| 251 | /* assoc variable) will be deleted. */ | ||
| 252 | |||
| 253 | static mps_res_t | ||
| 254 | dylan_scan_contig_weak(mps_ss_t mps_ss, | ||
| 255 | mps_addr_t *base, mps_addr_t *limit, | ||
| 256 | mps_addr_t *objectBase, mps_addr_t *assoc) | ||
| 257 | { | ||
| 258 | mps_addr_t *p; | ||
| 259 | mps_res_t res; | ||
| 260 | mps_addr_t r; | ||
| 261 | |||
| 262 | MPS_SCAN_BEGIN(mps_ss) { | ||
| 263 | p = base; | ||
| 264 | goto skip_inc; | ||
| 265 | loop: | ||
| 266 | ++p; | ||
| 267 | skip_inc: | ||
| 268 | if(p >= limit) | ||
| 269 | goto out; | ||
| 270 | r = *p; | ||
| 271 | if(((mps_word_t)r & 3) != 0) /* non-pointer */ | ||
| 272 | goto loop; | ||
| 273 | if(!MPS_FIX1(mps_ss, r)) | ||
| 274 | goto loop; | ||
| 275 | res = MPS_FIX2(mps_ss, p); | ||
| 276 | if(res == MPS_RES_OK) { | ||
| 277 | if(*p == 0 && r != 0) { | ||
| 278 | if(assoc != NULL) { | ||
| 279 | assoc[p-objectBase] = 0; /* delete corresponding entry */ | ||
| 280 | } | ||
| 281 | } | ||
| 282 | goto loop; | ||
| 283 | } | ||
| 284 | return res; | ||
| 285 | out: | ||
| 286 | assert(p == limit); | ||
| 287 | } MPS_SCAN_END(mps_ss); | ||
| 288 | |||
| 289 | return MPS_RES_OK; | ||
| 290 | } | ||
| 291 | |||
| 219 | 292 | ||
| 220 | /* dylan_scan_pat -- scan according to pattern | 293 | /* dylan_scan_pat -- scan according to pattern |
| 221 | * | 294 | * |
| @@ -450,6 +523,97 @@ static mps_res_t dylan_scan(mps_ss_t mps_ss, | |||
| 450 | } | 523 | } |
| 451 | 524 | ||
| 452 | 525 | ||
| 526 | static mps_res_t dylan_scan1_weak(mps_ss_t mps_ss, mps_addr_t *object_io) | ||
| 527 | { | ||
| 528 | mps_addr_t *assoc; | ||
| 529 | mps_addr_t *base; | ||
| 530 | mps_addr_t *p, q; | ||
| 531 | mps_res_t res; | ||
| 532 | mps_word_t *w; | ||
| 533 | mps_word_t fword, ff, fl; | ||
| 534 | mps_word_t h; | ||
| 535 | mps_word_t vword, vf, vl; | ||
| 536 | int header; | ||
| 537 | |||
| 538 | assert(object_io != NULL); | ||
| 539 | base = (mps_addr_t *)*object_io; | ||
| 540 | assert(base != NULL); | ||
| 541 | p = base; | ||
| 542 | |||
| 543 | header = *(int*)((char*)p - headerSIZE); | ||
| 544 | switch(headerType(header)) { | ||
| 545 | case realTYPE: | ||
| 546 | break; | ||
| 547 | case padTYPE: | ||
| 548 | *object_io = (mps_addr_t)((char*)p + headerPadSize(header)); | ||
| 549 | return MPS_RES_OK; | ||
| 550 | default: | ||
| 551 | notreached(); | ||
| 552 | break; | ||
| 553 | } | ||
| 554 | |||
| 555 | h = (mps_word_t)p[0]; | ||
| 556 | /* object should not be forwarded (as there is no forwarding method) */ | ||
| 557 | assert((h & 3) == 0); | ||
| 558 | |||
| 559 | mps_fix(mps_ss, p); | ||
| 560 | |||
| 561 | /* w points to wrapper */ | ||
| 562 | w = (mps_word_t *)p[0]; | ||
| 563 | |||
| 564 | assert(dylan_wrapper_check(w)); | ||
| 565 | |||
| 566 | ++p; /* skip header */ | ||
| 567 | |||
| 568 | fword = w[WF]; | ||
| 569 | fl = fword >> 2; | ||
| 570 | /* weak vectors should have at least one fixed field */ | ||
| 571 | /* (for assoc field) */ | ||
| 572 | assert(fl >= 1); | ||
| 573 | |||
| 574 | ff = fword & 3; | ||
| 575 | |||
| 576 | /* weak vectors should have traceable fixed format */ | ||
| 577 | assert(ff == 1); | ||
| 578 | |||
| 579 | assoc = (mps_addr_t *)p[0]; | ||
| 580 | |||
| 581 | vword = w[WV]; | ||
| 582 | vf = vword & 7; | ||
| 583 | vl = (mps_word_t)p[fl] >> 2; | ||
| 584 | |||
| 585 | /* weak vectors should be non-stretchy traceable */ | ||
| 586 | assert(vf == 2); | ||
| 587 | |||
| 588 | /* q is end of the object. There are fl fixed fields, vl variable */ | ||
| 589 | /* fields and another slot that contains the vector length */ | ||
| 590 | q = p + fl + vl + 1; | ||
| 591 | |||
| 592 | res = dylan_scan_contig_weak(mps_ss, p, q, base, assoc); | ||
| 593 | if(res != MPS_RES_OK) { | ||
| 594 | return res; | ||
| 595 | } | ||
| 596 | |||
| 597 | *object_io = AddHeader(q); | ||
| 598 | return MPS_RES_OK; | ||
| 599 | } | ||
| 600 | |||
| 601 | |||
| 602 | static mps_res_t dylan_scan_weak(mps_ss_t mps_ss, | ||
| 603 | mps_addr_t base, mps_addr_t limit) | ||
| 604 | { | ||
| 605 | mps_res_t res; | ||
| 606 | |||
| 607 | while(base < limit) { | ||
| 608 | res = dylan_scan1_weak(mps_ss, &base); | ||
| 609 | if(res) return res; | ||
| 610 | } | ||
| 611 | |||
| 612 | assert(base <= AddHeader(limit)); | ||
| 613 | |||
| 614 | return MPS_RES_OK; | ||
| 615 | } | ||
| 616 | |||
| 453 | static mps_addr_t dylan_skip(mps_addr_t object) | 617 | static mps_addr_t dylan_skip(mps_addr_t object) |
| 454 | { | 618 | { |
| 455 | mps_addr_t *p; /* cursor in object */ | 619 | mps_addr_t *p; /* cursor in object */ |
| @@ -563,6 +727,25 @@ static void dylan_pad(mps_addr_t addr, size_t fullSize) | |||
| 563 | } | 727 | } |
| 564 | 728 | ||
| 565 | 729 | ||
| 730 | static mps_addr_t dylan_no_isfwd(mps_addr_t object) | ||
| 731 | { | ||
| 732 | unused(object); | ||
| 733 | notreached(); | ||
| 734 | return 0; | ||
| 735 | } | ||
| 736 | |||
| 737 | static void dylan_no_fwd(mps_addr_t old, mps_addr_t new) | ||
| 738 | { | ||
| 739 | unused(old); unused(new); | ||
| 740 | notreached(); | ||
| 741 | } | ||
| 742 | |||
| 743 | static void dylan_no_pad(mps_addr_t addr, size_t size) | ||
| 744 | { | ||
| 745 | unused(addr); unused(size); | ||
| 746 | notreached(); | ||
| 747 | } | ||
| 748 | |||
| 566 | /* HeaderFormat -- format descriptor for this format */ | 749 | /* HeaderFormat -- format descriptor for this format */ |
| 567 | 750 | ||
| 568 | static struct mps_fmt_auto_header_s HeaderFormat = | 751 | static struct mps_fmt_auto_header_s HeaderFormat = |
| @@ -577,6 +760,20 @@ static struct mps_fmt_auto_header_s HeaderFormat = | |||
| 577 | }; | 760 | }; |
| 578 | 761 | ||
| 579 | 762 | ||
| 763 | /* HeaderWeakFormat -- format descriptor for this format */ | ||
| 764 | |||
| 765 | static struct mps_fmt_auto_header_s HeaderWeakFormat = | ||
| 766 | { | ||
| 767 | ALIGN, | ||
| 768 | dylan_scan_weak, | ||
| 769 | dylan_skip, | ||
| 770 | dylan_no_fwd, | ||
| 771 | dylan_no_isfwd, | ||
| 772 | dylan_no_pad, | ||
| 773 | (size_t)headerSIZE | ||
| 774 | }; | ||
| 775 | |||
| 776 | |||
| 580 | /* EnsureHeaderFormat -- create a format object for this format */ | 777 | /* EnsureHeaderFormat -- create a format object for this format */ |
| 581 | 778 | ||
| 582 | mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) | 779 | mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) |
| @@ -585,6 +782,14 @@ mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) | |||
| 585 | } | 782 | } |
| 586 | 783 | ||
| 587 | 784 | ||
| 785 | /* EnsureHeaderWeakFormat -- create a format object for the weak format */ | ||
| 786 | |||
| 787 | mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) | ||
| 788 | { | ||
| 789 | return mps_fmt_create_auto_header(mps_fmt_o, arena, &HeaderWeakFormat); | ||
| 790 | } | ||
| 791 | |||
| 792 | |||
| 588 | /* HeaderFormatCheck -- check an object in this format */ | 793 | /* HeaderFormatCheck -- check an object in this format */ |
| 589 | 794 | ||
| 590 | mps_res_t HeaderFormatCheck(mps_addr_t addr) | 795 | mps_res_t HeaderFormatCheck(mps_addr_t addr) |
| @@ -595,3 +800,14 @@ mps_res_t HeaderFormatCheck(mps_addr_t addr) | |||
| 595 | else | 800 | else |
| 596 | return MPS_RES_FAIL; | 801 | return MPS_RES_FAIL; |
| 597 | } | 802 | } |
| 803 | |||
| 804 | /* HeaderWeakFormatCheck -- check an object in this format */ | ||
| 805 | |||
| 806 | mps_res_t HeaderWeakFormatCheck(mps_addr_t addr) | ||
| 807 | { | ||
| 808 | if (addr != 0 && ((mps_word_t)addr & (ALIGN-1)) == 0 | ||
| 809 | && dylan_wrapper_check((mps_word_t *)((mps_word_t *)addr)[0])) | ||
| 810 | return MPS_RES_OK; | ||
| 811 | else | ||
| 812 | return MPS_RES_FAIL; | ||
| 813 | } | ||
diff --git a/mps/code/fmthe.h b/mps/code/fmthe.h index 5d42ffbd15e..0445f34d098 100644 --- a/mps/code/fmthe.h +++ b/mps/code/fmthe.h | |||
| @@ -10,10 +10,14 @@ | |||
| 10 | #include "mps.h" | 10 | #include "mps.h" |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | /* Format */ | 13 | /* Formats */ |
| 14 | extern mps_res_t EnsureHeaderFormat(mps_fmt_t *, mps_arena_t); | 14 | extern mps_res_t EnsureHeaderFormat(mps_fmt_t *, mps_arena_t); |
| 15 | extern mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *, mps_arena_t); | ||
| 15 | extern mps_res_t HeaderFormatCheck(mps_addr_t addr); | 16 | extern mps_res_t HeaderFormatCheck(mps_addr_t addr); |
| 17 | extern mps_res_t HeaderWeakFormatCheck(mps_addr_t addr); | ||
| 16 | 18 | ||
| 19 | /* dependent object function for weak pool */ | ||
| 20 | extern mps_addr_t dylan_weak_dependent(mps_addr_t); | ||
| 17 | 21 | ||
| 18 | /* Constants describing wrappers. Used only for debugging / testing */ | 22 | /* Constants describing wrappers. Used only for debugging / testing */ |
| 19 | #define WW 0 /* offset of Wrapper-Wrapper */ | 23 | #define WW 0 /* offset of Wrapper-Wrapper */ |
diff --git a/mps/code/fri4gc.gmk b/mps/code/fri4gc.gmk index a6b2c9b8b6f..05e41e8de23 100644 --- a/mps/code/fri4gc.gmk +++ b/mps/code/fri4gc.gmk | |||
| @@ -15,8 +15,8 @@ LIBS = -lm -pthread | |||
| 15 | 15 | ||
| 16 | include gc.gmk | 16 | include gc.gmk |
| 17 | 17 | ||
| 18 | CFLAGSDEBUG = -g -ggdb | 18 | CFLAGSDEBUG = -g |
| 19 | CFLAGSOPT = -O -g -ggdb | 19 | CFLAGSOPT = -O -g |
| 20 | 20 | ||
| 21 | CC = cc | 21 | CC = cc |
| 22 | 22 | ||
diff --git a/mps/code/poolawl.c b/mps/code/poolawl.c index ca7954c5791..d7f0992c40b 100644 --- a/mps/code/poolawl.c +++ b/mps/code/poolawl.c | |||
| @@ -792,9 +792,10 @@ static void AWLBlacken(Pool pool, TraceSet traceSet, Seg seg) | |||
| 792 | 792 | ||
| 793 | 793 | ||
| 794 | /* awlScanObject -- scan a single object */ | 794 | /* awlScanObject -- scan a single object */ |
| 795 | /* base and limit are both offset by the header size */ | ||
| 795 | 796 | ||
| 796 | static Res awlScanObject(Arena arena, AWL awl, ScanState ss, | 797 | static Res awlScanObject(Arena arena, AWL awl, ScanState ss, |
| 797 | FormatScanMethod scan, Addr base, Addr limit) | 798 | Format format, Addr base, Addr limit) |
| 798 | { | 799 | { |
| 799 | Res res; | 800 | Res res; |
| 800 | Bool dependent; /* is there a dependent object? */ | 801 | Bool dependent; /* is there a dependent object? */ |
| @@ -804,7 +805,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss, | |||
| 804 | AVERT(Arena, arena); | 805 | AVERT(Arena, arena); |
| 805 | AVERT(AWL, awl); | 806 | AVERT(AWL, awl); |
| 806 | AVERT(ScanState, ss); | 807 | AVERT(ScanState, ss); |
| 807 | AVER(FUNCHECK(scan)); | 808 | AVERT(Format, format); |
| 808 | AVER(base != 0); | 809 | AVER(base != 0); |
| 809 | AVER(base < limit); | 810 | AVER(base < limit); |
| 810 | 811 | ||
| @@ -817,7 +818,7 @@ static Res awlScanObject(Arena arena, AWL awl, ScanState ss, | |||
| 817 | SegSetSummary(dependentSeg, RefSetUNIV); | 818 | SegSetSummary(dependentSeg, RefSetUNIV); |
| 818 | } | 819 | } |
| 819 | 820 | ||
| 820 | res = (*scan)(ss, base, limit); | 821 | res = (*format->scan)(ss, base, limit); |
| 821 | if (res == ResOK) | 822 | if (res == ResOK) |
| 822 | ss->scannedSize += AddrOffset(base, limit); | 823 | ss->scannedSize += AddrOffset(base, limit); |
| 823 | 824 | ||
| @@ -836,10 +837,12 @@ static Res awlScanSinglePass(Bool *anyScannedReturn, | |||
| 836 | { | 837 | { |
| 837 | Addr base, limit, bufferScanLimit; | 838 | Addr base, limit, bufferScanLimit; |
| 838 | Addr p; | 839 | Addr p; |
| 840 | Addr hp; | ||
| 839 | Arena arena; | 841 | Arena arena; |
| 840 | AWL awl; | 842 | AWL awl; |
| 841 | AWLSeg awlseg; | 843 | AWLSeg awlseg; |
| 842 | Buffer buffer; | 844 | Buffer buffer; |
| 845 | Format format; | ||
| 843 | 846 | ||
| 844 | AVERT(ScanState, ss); | 847 | AVERT(ScanState, ss); |
| 845 | AVERT(Pool, pool); | 848 | AVERT(Pool, pool); |
| @@ -851,6 +854,9 @@ static Res awlScanSinglePass(Bool *anyScannedReturn, | |||
| 851 | arena = PoolArena(pool); | 854 | arena = PoolArena(pool); |
| 852 | AVERT(Arena, arena); | 855 | AVERT(Arena, arena); |
| 853 | 856 | ||
| 857 | format = pool->format; | ||
| 858 | AVERT(Format, format); | ||
| 859 | |||
| 854 | awlseg = Seg2AWLSeg(seg); | 860 | awlseg = Seg2AWLSeg(seg); |
| 855 | AVERT(AWLSeg, awlseg); | 861 | AVERT(AWLSeg, awlseg); |
| 856 | *anyScannedReturn = FALSE; | 862 | *anyScannedReturn = FALSE; |
| @@ -878,17 +884,19 @@ static Res awlScanSinglePass(Bool *anyScannedReturn, | |||
| 878 | p = AddrAdd(p, pool->alignment); | 884 | p = AddrAdd(p, pool->alignment); |
| 879 | continue; | 885 | continue; |
| 880 | } | 886 | } |
| 881 | objectLimit = (*pool->format->skip)(p); | 887 | hp = AddrAdd(p, format->headerSize); |
| 888 | objectLimit = (format->skip)(hp); | ||
| 882 | /* design.mps.poolawl.fun.scan.pass.object */ | 889 | /* design.mps.poolawl.fun.scan.pass.object */ |
| 883 | if (scanAllObjects | 890 | if (scanAllObjects |
| 884 | || (BTGet(awlseg->mark, i) && !BTGet(awlseg->scanned, i))) { | 891 | || (BTGet(awlseg->mark, i) && !BTGet(awlseg->scanned, i))) { |
| 885 | Res res = awlScanObject(arena, awl, ss, pool->format->scan, | 892 | Res res = awlScanObject(arena, awl, ss, pool->format, |
| 886 | p, objectLimit); | 893 | hp, objectLimit); |
| 887 | if (res != ResOK) | 894 | if (res != ResOK) |
| 888 | return res; | 895 | return res; |
| 889 | *anyScannedReturn = TRUE; | 896 | *anyScannedReturn = TRUE; |
| 890 | BTSet(awlseg->scanned, i); | 897 | BTSet(awlseg->scanned, i); |
| 891 | } | 898 | } |
| 899 | objectLimit = AddrSub(objectLimit, format->headerSize); | ||
| 892 | AVER(p < objectLimit); | 900 | AVER(p < objectLimit); |
| 893 | p = AddrAlignUp(objectLimit, pool->alignment); | 901 | p = AddrAlignUp(objectLimit, pool->alignment); |
| 894 | } | 902 | } |
| @@ -954,7 +962,8 @@ static Res AWLScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) | |||
| 954 | 962 | ||
| 955 | static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | 963 | static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) |
| 956 | { | 964 | { |
| 957 | Ref ref; | 965 | Ref clientRef; |
| 966 | Addr base; | ||
| 958 | Index i; | 967 | Index i; |
| 959 | AWL awl; | 968 | AWL awl; |
| 960 | AWLSeg awlseg; | 969 | AWLSeg awlseg; |
| @@ -970,15 +979,23 @@ static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 970 | awlseg = Seg2AWLSeg(seg); | 979 | awlseg = Seg2AWLSeg(seg); |
| 971 | AVERT(AWLSeg, awlseg); | 980 | AVERT(AWLSeg, awlseg); |
| 972 | 981 | ||
| 973 | ref = *refIO; | 982 | clientRef = *refIO; |
| 974 | i = awlIndexOfAddr(SegBase(seg), awl, ref); | ||
| 975 | |||
| 976 | ss->wasMarked = TRUE; | 983 | ss->wasMarked = TRUE; |
| 977 | 984 | ||
| 985 | base = AddrSub((Addr)clientRef, pool->format->headerSize); | ||
| 986 | /* can get an ambiguous reference to close to the base of the | ||
| 987 | * segment, so when we subtract the header we are not in the | ||
| 988 | * segment any longer. This isn't a real reference, | ||
| 989 | * so we can just skip it. */ | ||
| 990 | if (base < SegBase(seg)) { | ||
| 991 | return ResOK; | ||
| 992 | } | ||
| 993 | i = awlIndexOfAddr(SegBase(seg), awl, base); | ||
| 994 | |||
| 978 | switch(ss->rank) { | 995 | switch(ss->rank) { |
| 979 | case RankAMBIG: | 996 | case RankAMBIG: |
| 980 | /* not a real pointer if not aligned or not allocated */ | 997 | /* not a real pointer if not aligned or not allocated */ |
| 981 | if (!AddrIsAligned((Addr)ref, pool->alignment) || !BTGet(awlseg->alloc, i)) | 998 | if (!AddrIsAligned(base, pool->alignment) || !BTGet(awlseg->alloc, i)) |
| 982 | return ResOK; | 999 | return ResOK; |
| 983 | /* falls through */ | 1000 | /* falls through */ |
| 984 | case RankEXACT: | 1001 | case RankEXACT: |
| @@ -1012,6 +1029,7 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg) | |||
| 1012 | AWLSeg awlseg; | 1029 | AWLSeg awlseg; |
| 1013 | Index i; | 1030 | Index i; |
| 1014 | Count oldFree; | 1031 | Count oldFree; |
| 1032 | Format format; | ||
| 1015 | Count preservedInPlaceCount = (Count)0; | 1033 | Count preservedInPlaceCount = (Count)0; |
| 1016 | Size preservedInPlaceSize = (Size)0; | 1034 | Size preservedInPlaceSize = (Size)0; |
| 1017 | Size freed; /* amount reclaimed, in bytes */ | 1035 | Size freed; /* amount reclaimed, in bytes */ |
| @@ -1025,6 +1043,8 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg) | |||
| 1025 | awlseg = Seg2AWLSeg(seg); | 1043 | awlseg = Seg2AWLSeg(seg); |
| 1026 | AVERT(AWLSeg, awlseg); | 1044 | AVERT(AWLSeg, awlseg); |
| 1027 | 1045 | ||
| 1046 | format = pool->format; | ||
| 1047 | |||
| 1028 | base = SegBase(seg); | 1048 | base = SegBase(seg); |
| 1029 | 1049 | ||
| 1030 | i = 0; oldFree = awlseg->free; | 1050 | i = 0; oldFree = awlseg->free; |
| @@ -1046,7 +1066,9 @@ static void AWLReclaim(Pool pool, Trace trace, Seg seg) | |||
| 1046 | continue; | 1066 | continue; |
| 1047 | } | 1067 | } |
| 1048 | } | 1068 | } |
| 1049 | q = AddrAlignUp(pool->format->skip(p), pool->alignment); | 1069 | q = format->skip(AddrAdd(p, format->headerSize)); |
| 1070 | q = AddrSub(q, format->headerSize); | ||
| 1071 | q = AddrAlignUp(q, pool->alignment); | ||
| 1050 | j = awlIndexOfAddr(base, awl, q); | 1072 | j = awlIndexOfAddr(base, awl, q); |
| 1051 | AVER(j <= awlseg->grains); | 1073 | AVER(j <= awlseg->grains); |
| 1052 | if (BTGet(awlseg->mark, i)) { | 1074 | if (BTGet(awlseg->mark, i)) { |
| @@ -1123,6 +1145,7 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, | |||
| 1123 | AWL awl; | 1145 | AWL awl; |
| 1124 | AWLSeg awlseg; | 1146 | AWLSeg awlseg; |
| 1125 | Addr object, base, limit; | 1147 | Addr object, base, limit; |
| 1148 | Format format; | ||
| 1126 | 1149 | ||
| 1127 | AVERT(Pool, pool); | 1150 | AVERT(Pool, pool); |
| 1128 | AVERT(Seg, seg); | 1151 | AVERT(Seg, seg); |
| @@ -1134,6 +1157,8 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, | |||
| 1134 | awlseg = Seg2AWLSeg(seg); | 1157 | awlseg = Seg2AWLSeg(seg); |
| 1135 | AVERT(AWLSeg, awlseg); | 1158 | AVERT(AWLSeg, awlseg); |
| 1136 | 1159 | ||
| 1160 | format = pool->format; | ||
| 1161 | |||
| 1137 | base = SegBase(seg); | 1162 | base = SegBase(seg); |
| 1138 | object = base; | 1163 | object = base; |
| 1139 | limit = SegLimit(seg); | 1164 | limit = SegLimit(seg); |
| @@ -1162,7 +1187,10 @@ static void AWLWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, | |||
| 1162 | object = AddrAdd(object, pool->alignment); | 1187 | object = AddrAdd(object, pool->alignment); |
| 1163 | continue; | 1188 | continue; |
| 1164 | } | 1189 | } |
| 1165 | next = AddrAlignUp((*pool->format->skip)(object), pool->alignment); | 1190 | object = AddrAdd(object, format->headerSize); |
| 1191 | next = format->skip(object); | ||
| 1192 | next = AddrSub(next, format->headerSize); | ||
| 1193 | next = AddrAlignUp(next, pool->alignment); | ||
| 1166 | if (BTGet(awlseg->mark, i) && BTGet(awlseg->scanned, i)) | 1194 | if (BTGet(awlseg->mark, i) && BTGet(awlseg->scanned, i)) |
| 1167 | (*f)(object, pool->format, pool, p, s); | 1195 | (*f)(object, pool->format, pool, p, s); |
| 1168 | object = next; | 1196 | object = next; |
diff --git a/mps/code/poollo.c b/mps/code/poollo.c index 02db2634d9c..779c9d3e7e9 100644 --- a/mps/code/poollo.c +++ b/mps/code/poollo.c | |||
| @@ -329,6 +329,7 @@ static void loSegReclaim(LOSeg loseg, Trace trace) | |||
| 329 | Count bytesReclaimed = (Count)0; | 329 | Count bytesReclaimed = (Count)0; |
| 330 | Seg seg; | 330 | Seg seg; |
| 331 | LO lo; | 331 | LO lo; |
| 332 | Format format; | ||
| 332 | Count preservedInPlaceCount = (Count)0; | 333 | Count preservedInPlaceCount = (Count)0; |
| 333 | Size preservedInPlaceSize = (Size)0; | 334 | Size preservedInPlaceSize = (Size)0; |
| 334 | 335 | ||
| @@ -341,6 +342,9 @@ static void loSegReclaim(LOSeg loseg, Trace trace) | |||
| 341 | limit = SegLimit(seg); | 342 | limit = SegLimit(seg); |
| 342 | marked = FALSE; | 343 | marked = FALSE; |
| 343 | 344 | ||
| 345 | format = LOPool(lo)->format; | ||
| 346 | AVERT(Format, format); | ||
| 347 | |||
| 344 | /* i is the index of the current pointer, | 348 | /* i is the index of the current pointer, |
| 345 | * p is the actual address that is being considered. | 349 | * p is the actual address that is being considered. |
| 346 | * j and q act similarly for a pointer which is used to | 350 | * j and q act similarly for a pointer which is used to |
| @@ -370,7 +374,8 @@ static void loSegReclaim(LOSeg loseg, Trace trace) | |||
| 370 | p = AddrAdd(p, LOPool(lo)->alignment); | 374 | p = AddrAdd(p, LOPool(lo)->alignment); |
| 371 | continue; | 375 | continue; |
| 372 | } | 376 | } |
| 373 | q = (*LOPool(lo)->format->skip)(p); | 377 | q = (*format->skip)(AddrAdd(p, format->headerSize)); |
| 378 | q = AddrSub(q, format->headerSize); | ||
| 374 | if(BTGet(loseg->mark, i)) { | 379 | if(BTGet(loseg->mark, i)) { |
| 375 | marked = TRUE; | 380 | marked = TRUE; |
| 376 | ++preservedInPlaceCount; | 381 | ++preservedInPlaceCount; |
| @@ -409,6 +414,7 @@ static void LOWalk(Pool pool, Seg seg, | |||
| 409 | LO lo; | 414 | LO lo; |
| 410 | LOSeg loseg; | 415 | LOSeg loseg; |
| 411 | Index i, limit; | 416 | Index i, limit; |
| 417 | Format format; | ||
| 412 | 418 | ||
| 413 | AVERT(Pool, pool); | 419 | AVERT(Pool, pool); |
| 414 | AVERT(Seg, seg); | 420 | AVERT(Seg, seg); |
| @@ -420,6 +426,9 @@ static void LOWalk(Pool pool, Seg seg, | |||
| 420 | loseg = SegLOSeg(seg); | 426 | loseg = SegLOSeg(seg); |
| 421 | AVERT(LOSeg, loseg); | 427 | AVERT(LOSeg, loseg); |
| 422 | 428 | ||
| 429 | format = pool->format; | ||
| 430 | AVERT(Format, format); | ||
| 431 | |||
| 423 | base = SegBase(seg); | 432 | base = SegBase(seg); |
| 424 | limit = SegSize(seg) >> lo->alignShift; | 433 | limit = SegSize(seg) >> lo->alignShift; |
| 425 | i = 0; | 434 | i = 0; |
| @@ -449,7 +458,9 @@ static void LOWalk(Pool pool, Seg seg, | |||
| 449 | ++i; | 458 | ++i; |
| 450 | continue; | 459 | continue; |
| 451 | } | 460 | } |
| 452 | next = (*pool->format->skip)(object); | 461 | object = AddrAdd(object, format->headerSize); |
| 462 | next = (*format->skip)(object); | ||
| 463 | next = AddrSub(object, format->headerSize); | ||
| 453 | j = loIndexOfAddr(base, lo, next); | 464 | j = loIndexOfAddr(base, lo, next); |
| 454 | AVER(i < j); | 465 | AVER(i < j); |
| 455 | (*f)(object, pool->format, pool, p, s); | 466 | (*f)(object, pool->format, pool, p, s); |
| @@ -474,9 +485,9 @@ static Res LOInit(Pool pool, va_list arg) | |||
| 474 | 485 | ||
| 475 | format = va_arg(arg, Format); | 486 | format = va_arg(arg, Format); |
| 476 | AVERT(Format, format); | 487 | AVERT(Format, format); |
| 477 | 488 | ||
| 478 | lo = PoolPoolLO(pool); | 489 | lo = PoolPoolLO(pool); |
| 479 | 490 | ||
| 480 | pool->format = format; | 491 | pool->format = format; |
| 481 | lo->poolStruct.alignment = format->alignment; | 492 | lo->poolStruct.alignment = format->alignment; |
| 482 | lo->alignShift = | 493 | lo->alignShift = |
| @@ -508,7 +519,7 @@ static void LOFinish(Pool pool) | |||
| 508 | { | 519 | { |
| 509 | LO lo; | 520 | LO lo; |
| 510 | Ring node, nextNode; | 521 | Ring node, nextNode; |
| 511 | 522 | ||
| 512 | AVERT(Pool, pool); | 523 | AVERT(Pool, pool); |
| 513 | lo = PoolPoolLO(pool); | 524 | lo = PoolPoolLO(pool); |
| 514 | AVERT(LO, lo); | 525 | AVERT(LO, lo); |
| @@ -618,7 +629,7 @@ static void LOBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) | |||
| 618 | seg = BufferSeg(buffer); | 629 | seg = BufferSeg(buffer); |
| 619 | AVERT(Seg, seg); | 630 | AVERT(Seg, seg); |
| 620 | AVER(init <= limit); | 631 | AVER(init <= limit); |
| 621 | 632 | ||
| 622 | loseg = SegLOSeg(seg); | 633 | loseg = SegLOSeg(seg); |
| 623 | AVERT(LOSeg, loseg); | 634 | AVERT(LOSeg, loseg); |
| 624 | AVER(loseg->lo == lo); | 635 | AVER(loseg->lo == lo); |
| @@ -657,7 +668,7 @@ static Res LOWhiten(Pool pool, Trace trace, Seg seg) | |||
| 657 | { | 668 | { |
| 658 | LO lo; | 669 | LO lo; |
| 659 | unsigned long bits; | 670 | unsigned long bits; |
| 660 | 671 | ||
| 661 | AVERT(Pool, pool); | 672 | AVERT(Pool, pool); |
| 662 | lo = PoolPoolLO(pool); | 673 | lo = PoolPoolLO(pool); |
| 663 | AVERT(LO, lo); | 674 | AVERT(LO, lo); |
| @@ -689,14 +700,14 @@ static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 689 | { | 700 | { |
| 690 | LO lo; | 701 | LO lo; |
| 691 | LOSeg loseg; | 702 | LOSeg loseg; |
| 692 | Ref ref; | 703 | Ref clientRef; |
| 704 | Addr base; | ||
| 693 | 705 | ||
| 694 | AVERT_CRITICAL(Pool, pool); | 706 | AVERT_CRITICAL(Pool, pool); |
| 695 | AVERT_CRITICAL(ScanState, ss); | 707 | AVERT_CRITICAL(ScanState, ss); |
| 696 | AVERT_CRITICAL(Seg, seg); | 708 | AVERT_CRITICAL(Seg, seg); |
| 697 | AVER_CRITICAL(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); | 709 | AVER_CRITICAL(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); |
| 698 | AVER_CRITICAL(refIO != NULL); | 710 | AVER_CRITICAL(refIO != NULL); |
| 699 | ref = *refIO; | ||
| 700 | lo = PARENT(LOStruct, poolStruct, pool); | 711 | lo = PARENT(LOStruct, poolStruct, pool); |
| 701 | AVERT_CRITICAL(LO, lo); | 712 | AVERT_CRITICAL(LO, lo); |
| 702 | loseg = SegLOSeg(seg); | 713 | loseg = SegLOSeg(seg); |
| @@ -704,9 +715,19 @@ static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 704 | 715 | ||
| 705 | ss->wasMarked = TRUE; /* design.mps.fix.protocol.was-marked */ | 716 | ss->wasMarked = TRUE; /* design.mps.fix.protocol.was-marked */ |
| 706 | 717 | ||
| 718 | clientRef = *refIO; | ||
| 719 | base = AddrSub((Addr)clientRef, pool->format->headerSize); | ||
| 720 | /* can get an ambiguous reference to close to the base of the | ||
| 721 | * segment, so when we subtract the header we are not in the | ||
| 722 | * segment any longer. This isn't a real reference, | ||
| 723 | * so we can just skip it. */ | ||
| 724 | if (base < SegBase(seg)) { | ||
| 725 | return ResOK; | ||
| 726 | } | ||
| 727 | |||
| 707 | switch(ss->rank) { | 728 | switch(ss->rank) { |
| 708 | case RankAMBIG: | 729 | case RankAMBIG: |
| 709 | if(!AddrIsAligned(ref, PoolAlignment(pool))) { | 730 | if(!AddrIsAligned(base, PoolAlignment(pool))) { |
| 710 | return ResOK; | 731 | return ResOK; |
| 711 | } | 732 | } |
| 712 | /* fall through */ | 733 | /* fall through */ |
| @@ -714,7 +735,7 @@ static Res LOFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) | |||
| 714 | case RankEXACT: | 735 | case RankEXACT: |
| 715 | case RankFINAL: | 736 | case RankFINAL: |
| 716 | case RankWEAK: { | 737 | case RankWEAK: { |
| 717 | Size i = AddrOffset(SegBase(seg), (Addr)ref) >> lo->alignShift; | 738 | Size i = AddrOffset(SegBase(seg), base) >> lo->alignShift; |
| 718 | 739 | ||
| 719 | if(!BTGet(loseg->mark, i)) { | 740 | if(!BTGet(loseg->mark, i)) { |
| 720 | ss->wasMarked = FALSE; /* design.mps.fix.protocol.was-marked */ | 741 | ss->wasMarked = FALSE; /* design.mps.fix.protocol.was-marked */ |