|
|
1.1 root 1: /* Copyright 1989 by AT&T Bell Laboratories */
2: #include "tags.h"
3: #include "descriptor.h"
4:
5: #ifdef GCDEBUG
6: #define chatarg chatting
7: #endif
8:
9: /* registers:
10: inside arenas: allocation is on word boundaries and in units a multiple
11: of a word (4 bytes) so words with odd contents are not pointers.
12: Conversely, if a word is pointed to by a pointer p (i.e., the word
13: is p[0], then p[-1] contains a descriptor of the record the word is in:
14: struct {
15: unsigned int flg:width_tags; least sig bits
16: int len:32-width_tags;
17: } mem;
18: flag is even: look in previous word for descriptor
19: flag is odd: this is the descriptor.
20: len gives the number of 4-byte words. (not incl. descriptor)
21: For any record in a collectable area, len>0
22: when the gc isn't running:
23: flag=1 record containing pointers & integers
24: flag=5 record containing no pointers
25: flag=7 look in p[-len-1] for descriptor
26: when gc is running, descriptor in the TO space:
27: as above, but flag=3 not possible
28: when the gc is running, descriptor in the FROM space:
29: flag=1 unmoved record containing pointers & integers
30: flag=3 record has already been moved, in which case,
31: p[0] is the forwarding pointer.
32: flag=5 unmoved record containing no pointers
33: flag=7 look in p[-len-1] for descriptor
34:
35: In a record containing pointers & integers,
36: any even number is a pointer, any odd number is not a pointer.
37:
38: There are occasional pointers to places outside the GC arena;
39: these get copied intact.
40:
41: Format of linked list of stored-into ref cells:
42: p[0] = pointer to a ref or array cell that's been stored into.
43: p[1] = index within object of modified slot
44: p[2] = next object on list (1 for nil)
45:
46: */
47:
48: int ** (*gmore)();
49: static int **to_ptr, **to_lim, **to_lim0;
50: static int **lowest, **highest;
51: static int repair;
52: static int any_weak;
53:
54: extern int store_preserve, preserving;
55:
56: /*static
57: xgc(refloc)
58: register int *refloc;*/
59: #define xgc(refloc)\
60: {register int *m = *((int**)(refloc));\
61: /* if refloc is not a pointer,\
62: or is not in the allocated area, just leave it alone */\
63: if(is_ptr(m) && (m >= (int*)lowest && m < (int*)highest))\
64: { m--;\
65: for(;;)\
66: {\
67: switch(get_tag(m)) {\
68: case tag_backptr:\
69: m -= get_len(m);\
70: continue;\
71: case tag_embedded:\
72: m--; continue;\
73: case tag_string:\
74: case tag_bytearray:\
75: {register int **i=(int**)m, **j=to_ptr, len1 = (get_len(m)+7)>>2;\
76: if (j+len1 > to_lim) do {if (repair) \
77: {repair=0; to_lim=to_lim0;} \
78: else to_lim=gmore();}\
79: while (j+len1 > to_lim);\
80: do {*j++ = *i++;} while (--len1 > 0);\
81: if (repair) \
82: {if (to_ptr+5 < to_lim) \
83: {* -- to_lim = ((int**)m)[1]; \
84: * -- to_lim = m+1; \
85: } \
86: else {repair=0; to_lim=to_lim0;} \
87: } \
88: ((int**)m)[1]= 1+(int*)to_ptr;\
89: to_ptr = j;\
90: }\
91: (*m) = tag_forwarded;\
92: *(int*)(refloc) += ((int*)m)[1] - ((int)(m+1));\
93: break;\
94: case tag_array:\
95: if (preserving) \
96: {*to_ptr++ = (int*)(16*3+1); \
97: *to_ptr++ = m+1; \
98: *to_ptr++ = (int*)-1; \
99: *to_ptr++ = (int*)store_preserve; \
100: store_preserve = (int) (to_ptr-3); \
101: } \
102: case tag_record:\
103: {register int **i=(int**)m, **j=to_ptr, len1 = get_len(m)+1;\
104: if (j+len1 > to_lim) do {if (repair) \
105: {repair=0; to_lim=to_lim0;} \
106: else to_lim=gmore();}\
107: while (j+len1 > to_lim);\
108: do {*j++ = *i++;} while (--len1 > 0);\
109: if (repair) \
110: {if (to_ptr+5 < to_lim) \
111: {* -- to_lim = ((int**)m)[1]; \
112: * -- to_lim = m+1; \
113: } \
114: else {repair=0; to_lim=to_lim0;} \
115: } \
116: ((int**)m)[1]= 1+(int*)to_ptr;\
117: to_ptr = j;\
118: }\
119: (*m) = tag_forwarded;\
120: /* fall through */\
121: case tag_forwarded: *(int*)(refloc) += ((int*)m)[1] - ((int)(m+1));\
122: break;\
123: case tag_suspension:\
124: {register int **i=(int**)m, **j=to_ptr, len1 = 2;\
125: if (j+len1 > to_lim) do {if (repair) \
126: {repair=0; to_lim=to_lim0;} \
127: else to_lim=gmore();}\
128: while (j+len1 > to_lim);\
129: do {*j++ = *i++;} while (--len1 > 0);\
130: if (repair) \
131: {if (to_ptr+5 < to_lim) \
132: {* -- to_lim = ((int**)m)[1]; \
133: * -- to_lim = m+1; \
134: } \
135: else {repair=0; to_lim=to_lim0;} \
136: } \
137: ((int**)m)[1]= 1+(int*)to_ptr;\
138: to_ptr = j;\
139: }\
140: (*m) = tag_forwarded;\
141: *(int*)(refloc) += ((int*)m)[1] - ((int)(m+1));\
142: break;\
143: default: /* function pointers */\
144: m--; continue;\
145: }\
146: break;\
147: }\
148: }\
149: }
150:
151: int target;
152:
153: gc(from_low, /* lowest address in space to be collected from */
154: from_high, /* higher than any ... */
155: to_low, /* lowest address in space to copy into */
156: to_high, /* limit address to copy into */
157: to_done, /* to-space is already copied into up to here */
158: to_where, /* (by-ref) just past highest address copied into */
159: misc_roots, /* vector (0-terminated) of ptrs to possible root words */
160: store_list, /* head of linked list of store-pointers */
161: get_more, /* procedure to call to increase to_lim */
162: first_root /* (optional) address of interesting root to trace;
163: if present, then to_done must equal to_low */
164: )
165: int **from_low, **from_high, ***misc_roots,
166: **to_low, **to_high, **to_done,
167: ***to_where, **store_list;
168: int *first_root;
169: int ** (*get_more)();
170: {
171: any_weak = 0;
172: gmore=get_more;
173: to_ptr = to_done;
174: to_lim0 = to_lim = to_high;
175: lowest=from_low;
176: highest=from_high;
177:
178: repair=0;
179: if (first_root)
180: {register int x;
181: int **blast_begin = to_low;
182: repair=1;
183: xgc(first_root);
184: x = (int) to_done;
185: while (x<(int)to_ptr)
186: {register int p = x+4;
187: {register int descr = *(int *)(x);
188: if (contains_no_ptrs(descr)) {x += ((get_len(x)+7)&~3);
189: continue;}
190: x += get_lenz(x) * 4 + 4;
191: }
192: do{xgc(p); p+=4;} while (p<x);
193: }
194: blast_write(blast_begin, x, *first_root);
195: if (repair)
196: {while(to_lim<to_lim0)
197: {int *loc = *to_lim++;
198: int *old = *to_lim++;
199: loc[-1] = ((int*)(loc[0]))[-1];
200: loc[0] = (int)old;
201: }
202: return 0;
203: }
204: }
205:
206:
207: /* do the refs */
208: #ifdef GCDEBUG
209: chatarg("\nto_ptr at %x... ",to_ptr);
210: chatting("beginning refs... ");
211: #endif
212: {register int **px;
213: #ifdef GCDEBUG
214: int count=0;
215: #endif
216: for(px=store_list; ((int)px)!=1; px= (int**) (px[2]))
217: {register int **r;
218: #ifdef GCDEBUG
219: count++;
220: #endif
221: r = (int**)(px[0])+(((int)(px[1]))>>1);
222: if (r>=from_low && r < from_high) continue;
223: if (preserving)
224: {*to_ptr++ = (int*)(16*3+1);
225: *to_ptr++ = px[0];
226: *to_ptr++ = px[1];
227: *to_ptr++ = (int*)store_preserve;
228: store_preserve = (int) (to_ptr-3);
229: }
230: xgc(r);
231: }
232: #ifdef GCDEBUG
233: chatting("(%d refs)\n",count);
234: #endif
235: }
236:
237: /* do misc. roots */
238: #ifdef GCDEBUG
239: chatarg("to_ptr at %x... ",to_ptr);
240: chatting("beginning misc roots\n");
241: #endif
242: { register int ***p;
243: for(p=misc_roots; *p; p++) xgc(*p);
244: }
245:
246: /* finish the new space */
247: #ifdef GCDEBUG
248: chatarg("to_ptr at %x... ",to_ptr);
249: chatting("finishing new space\n");
250: #endif
251: {register int x = (int)to_low;
252: while (x<(int)to_ptr)
253: {register int p = x+4;
254: {register int descr = *(int *)(x);
255: if (contains_no_ptrs(descr))
256: {x += ((get_len(x)+7)&~3);
257: continue;}
258: x += get_lenz(x) * 4 + 4;
259: if (descr == tag_suspension + 2*power_tags)
260: {any_weak=1; continue;}
261: }
262: do{xgc(p); p+=4;} while (p<x);
263: }
264: }
265: #ifdef GCDEBUG
266: chatarg("to_ptr at %x... ",to_ptr);
267: #endif
268: if (any_weak)
269: {register int x = (int)to_low;
270: #ifdef GCDEBUG
271: chatting("doing weak pointers\n");
272: #endif
273: while (x<(int)to_ptr)
274: {int *p = ((int*)x)+1;
275: int descr = *(int *)(x);
276: if (contains_no_ptrs(descr))
277: {x += ((get_len(x)+7)&~3);
278: continue;}
279: x += get_lenz(x) * 4 + 4;
280: if (descr == tag_suspension + 2*power_tags)
281: {int *m = ((int*)*p)-1;
282: if ((!(((int)m)&1)) && m >= (int*)from_low && m <= (int*)from_high)
283: for(;;)
284: {switch(get_tag(m))
285: {case tag_string: case tag_bytearray:
286: case tag_array: case tag_record:
287: case tag_suspension:
288: *p = 1;
289: p[-1]=tag_suspension+3*power_tags;
290: break;
291: case tag_forwarded:
292: *p += m[1] - (int) (m+1);
293: break;
294: case tag_backptr: m -= get_len(m);
295: continue;
296: case tag_embedded:
297: default:
298: m--;
299: continue;
300: }
301: break;
302: }
303: }
304: }
305: }
306: #ifdef GCDEBUG
307: chatarg("to_ptr at %x... ",to_ptr);
308: chatting("gc done\n");
309: #endif
310: if (target) trace(to_low,target,target+4);
311: *to_where = to_ptr;
312: return 1;
313: }
314:
315: blockmove(from,to,words) register int * from, *to; register int words;
316: {
317: if (!words) return;
318: if (from<to && from+words >to)
319: {from+=words; to+=words;
320: do {*--to = *--from;} while (--words > 0);
321: }
322: else do {*to++ = *from++;} while (--words > 0);
323: }
324:
325: moveback
326: (from_low, /* lowest address in space to be collected from */
327: from_high, /* higher than any ... */
328: to_low, /* lowest address in space to copy into */
329: misc_roots /* vector (0-terminated) of ptrs to possible root words */
330: )
331: int *from_low, *from_high, **misc_roots,
332: *to_low;
333: { register int *x, offset = sizeof(int)*(to_low-from_low);
334:
335: #define INRANGE(x) (((int)(x) >= (int)from_low) && \
336: ((int)(x) < (int)from_high) )
337: #define ADJUST1(x) (INRANGE(x)?(x)+=offset:0)
338: #define ADJUST(x) (is_ptr(x)?ADJUST1(x):0)
339:
340: /* do misc. roots */
341: #ifdef GCDEBUG
342: chatting("misc roots... ");
343: #endif
344: { register int **p;
345: for(p=misc_roots; *p; p++) ADJUST(**p);
346: }
347:
348: /* finish the new space */
349: #ifdef GCDEBUG
350: chatting("finishing... ");
351: #endif
352: x=from_low;
353: while (x<from_high)
354: if (contains_no_ptrs(*x))
355: x += (get_len(x)+7)>>2;
356: else {register int i = get_lenz(x);
357: ++x;
358: do {ADJUST(*x); x++;} while (--i > 0);
359: }
360: blockmove(from_low,to_low,from_high-from_low);
361: #ifdef GCDEBUG
362: chatting("done\n");
363: #endif
364: }
365:
366: relocate(start,end,stuff)
367: int start, end; int *stuff;
368:
369: {int *x=stuff, *done= stuff + (end-start)/4;
370: int adjust = ((int)stuff) - start;
371: while (x<done)
372: if (contains_no_ptrs(*x))
373: x += (get_len(x)+7)>>2;
374: else {register int i = get_lenz(x);
375: ++x;
376: do {if ( (*x & 1) == 0
377: && *x >= start && *x < end)
378: *x += adjust;
379: x++;}
380: while (--i > 0);
381: }
382: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.