aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/awluthe.c326
-rw-r--r--mps/code/comm.gmk12
-rw-r--r--mps/code/fmthe.c218
-rw-r--r--mps/code/fmthe.h6
-rw-r--r--mps/code/fri4gc.gmk4
-rw-r--r--mps/code/poolawl.c54
-rw-r--r--mps/code/poollo.c43
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
30static 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
42static 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
53static 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
62static 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
72static 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
86static 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
122static 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 */
151static 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 */
160static 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 */
171static 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
180static 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
244struct guff_s {
245 mps_arena_t arena;
246 mps_thr_t thr;
247};
248
249static 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
301int 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
280all: mpmss sacss amcss amcsshe amsss segsmss awlut \ 280all: 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
292testrun: mpmss apss sacss amcss amcsshe amsss segsmss awlut mpsicv lockcov \ 292testrun: 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
306mpmss sacss amcss amcssth amcsshe amsss segsmss awlut awlutth \ 307mpmss 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
222extern 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
253static mps_res_t
254dylan_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
526static 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
602static 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
453static mps_addr_t dylan_skip(mps_addr_t object) 617static 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
730static mps_addr_t dylan_no_isfwd(mps_addr_t object)
731{
732 unused(object);
733 notreached();
734 return 0;
735}
736
737static void dylan_no_fwd(mps_addr_t old, mps_addr_t new)
738{
739 unused(old); unused(new);
740 notreached();
741}
742
743static 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
568static struct mps_fmt_auto_header_s HeaderFormat = 751static 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
765static 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
582mps_res_t EnsureHeaderFormat(mps_fmt_t *mps_fmt_o, mps_arena_t arena) 779mps_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
787mps_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
590mps_res_t HeaderFormatCheck(mps_addr_t addr) 795mps_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
806mps_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 */
14extern mps_res_t EnsureHeaderFormat(mps_fmt_t *, mps_arena_t); 14extern mps_res_t EnsureHeaderFormat(mps_fmt_t *, mps_arena_t);
15extern mps_res_t EnsureHeaderWeakFormat(mps_fmt_t *, mps_arena_t);
15extern mps_res_t HeaderFormatCheck(mps_addr_t addr); 16extern mps_res_t HeaderFormatCheck(mps_addr_t addr);
17extern mps_res_t HeaderWeakFormatCheck(mps_addr_t addr);
16 18
19/* dependent object function for weak pool */
20extern 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
16include gc.gmk 16include gc.gmk
17 17
18CFLAGSDEBUG = -g -ggdb 18CFLAGSDEBUG = -g
19CFLAGSOPT = -O -g -ggdb 19CFLAGSOPT = -O -g
20 20
21CC = cc 21CC = 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
796static Res awlScanObject(Arena arena, AWL awl, ScanState ss, 797static 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
955static Res AWLFix(Pool pool, ScanState ss, Seg seg, Ref *refIO) 963static 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 */