Annotation of researchv10no/cmd/sml/src/runtime/gc.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.