Changeset 13293


Ignore:
Timestamp:
Dec 12, 2009, 2:07:08 AM (10 years ago)
Author:
gz
Message:

Third try, I think this approach works in all cases: keep hash tables
(as well as populations) on WEAKVLL. Handle weak-on-value hash tables
as well as weak-on-key. Don't mess with refbits, just special-case
weak hash vectors in mark_memoized_area. This leaves open the
possiblity of using refbits in mark_weak_hash_vector and reaphashv,
though I didn't do that yet (want to test what I've got so far).

Location:
branches/working-0711/ccl/lisp-kernel
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/working-0711/ccl/lisp-kernel/gc-common.c

    r13290 r13293  
    227227  int tag;
    228228
     229  /* TODO: hashv might be in old space, in which case should use refbits
     230     rather than touching all entries
     231  */
     232
    229233  while (npairs--) {
    230234    if (weak_on_value) {
     
    252256    pairp += 2;
    253257  }
     258  deref(hashv, 1) = lisp_global(WEAKVLL);
     259  lisp_global(WEAKVLL) = untag(hashv);
    254260}
    255261
     
    341347
    342348  elements -= skip;
     349
     350  /* TODO: the hash table might be in old space, in which case should use refbits
     351     rather than touching all entries
     352  */
    343353
    344354  for (i = 0; i<elements; i+=2, pairp+=2) {
     
    849859}
    850860
     861void
     862init_weakvll ()
     863{
     864  GCweakvll = (LispObj)NULL;
     865
     866  if (GCn_ephemeral_dnodes) {
     867    /* For egc case, initialize GCweakvll with weak vectors not in the
     868       GC area.  Weak vectors in the GC area will be added during marking.
     869    */
     870    LispObj this = lisp_global(WEAKVLL); /* all weak vectors as of last gc */
     871    LispObj *tenured_low = (LispObj *)tenured_area->low;
     872    natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
     873    bitvector refbits = tenured_area->refbits;
     874
     875    while (this) {
     876      LispObj *base = ptr_from_lispobj(this);
     877      LispObj next = base[1];
     878      natural dnode = gc_dynamic_area_dnode(this);
     879      if (dnode < GCndynamic_dnodes_in_area) {
     880        base[1] = (LispObj)NULL; /* drop it, might be garbage */
     881      } else {
     882        base[1] = GCweakvll;
     883        GCweakvll = ptr_to_lispobj(base);
     884        if (header_subtag(base[0]) == subtag_weak) {
     885          dnode = area_dnode(&base[3], tenured_low);
     886          if (dnode < tenured_dnodes) {
     887            clr_bit(refbits, dnode); /* Don't treat population.data as root */
     888          }
     889        } else {
     890          if (header_subtag(base[0]) != subtag_hash_vector)
     891            Bug(NULL, "Unexpected entry " LISP " -> " LISP " on WEAKVLL", base, base[0]);
     892          /* hash vectors are already singled out for special processing if they */
     893          /* have any ephemeral keys, but not if they have ephemeral values. */
     894          if (((hash_table_vector_header *)base)->flags & nhash_weak_value_mask) {
     895            dnode = area_dnode(&base[0], tenured_low);
     896            if (dnode < tenured_dnodes) {
     897              set_bit(refbits, dnode); /* need to look at it anyway */
     898            }
     899          }
     900        }
     901      }
     902      this = next;
     903    }
     904  }
     905  lisp_global(WEAKVLL) = (LispObj)NULL;
     906}
     907
     908 
     909void
     910preforward_weakvll ()
     911{
     912  /* reset population refbits for forwarding */
     913  if (GCn_ephemeral_dnodes) {
     914    LispObj this = lisp_global(WEAKVLL);
     915    LispObj *tenured_low = (LispObj *)tenured_area->low;
     916    natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
     917    bitvector refbits = tenured_area->refbits;
     918
     919    while (this) {
     920      LispObj *base = ptr_from_lispobj(this);
     921      if (header_subtag(base[0]) == subtag_weak) {
     922        natural dnode = area_dnode(&base[3], tenured_low);
     923        if (base[3] >= GCarealow) {
     924          if (dnode < tenured_dnodes) {
     925            set_bit(refbits, dnode);
     926          }
     927        }
     928        /* might have set termination list to a new pointer */
     929        if ((base[2] >> population_termination_bit) && (base[4] >= GCarealow)) {
     930          if ((dnode + 1) < tenured_dnodes) {
     931            set_bit(refbits, dnode+1);
     932          }
     933        }
     934      }
     935      this = base[1];
     936    }
     937  }
     938}
     939
     940
     941void
     942forward_weakvll_links()
     943{
     944  LispObj *ptr = &(lisp_global(WEAKVLL)), this, new, old;
     945
     946  while (this = *ptr) {
     947    old = this + fulltag_misc;
     948    new = node_forwarding_address(old);
     949    if (old != new) {
     950      *ptr = untag(new);
     951    }
     952    ptr = &(deref(new,1));
     953  }
     954}
     955
     956
     957
     958
     959
    851960LispObj
    852961node_forwarding_address(LispObj node)
     
    9161025  }
    9171026}
    918 
    919 void
    920 forward_weakvll()
    921 {
    922   LispObj *ptr = &(lisp_global(WEAKVLL)), this, new, old;
    923 
    924   while (this = *ptr) {
    925     old = this + fulltag_misc;
    926     new = node_forwarding_address(old);
    927     if (old != new) {
    928       *ptr = untag(new);
    929     }
    930     ptr = &(deref(new,1));
    931   }
    932 }
    933 
    9341027
    9351028void
     
    11451238
    11461239  if (GCephemeral_low) {
    1147     weak_method = 1;   /* egc, so use faster algorithm */
    11481240    if ((oldfree-g1_area->low) < g1_area->threshold) {
    11491241      to = g1_area;
     
    12141306
    12151307    zero_bits(GCmarkbits, GCndnodes_in_area);
    1216     GCweakvll = (LispObj)NULL;
    1217 
    1218     if (GCn_ephemeral_dnodes) {
    1219       /* For egc case, initialize GCweakvll with populations not in the
    1220          GC area.  Weak hash vectors, and populations in the GC area,
    1221          will be added during marking.
    1222       */
    1223       LispObj this = lisp_global(WEAKVLL); /* all populations as of last gc */
    1224       LispObj *tenured_low = (LispObj *)tenured_area->low;
    1225       natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
    1226       bitvector refbits = tenured_area->refbits;
    1227 
    1228       while (this) {
    1229         LispObj *base = ptr_from_lispobj(this);
    1230         LispObj next = base[1];
    1231         natural dnode = gc_dynamic_area_dnode(this);
    1232         if (dnode >= GCndynamic_dnodes_in_area) {
    1233           base[1] = GCweakvll;
    1234           GCweakvll = ptr_to_lispobj(base);
    1235           /* Since will be doing weak processing, don't treat the data as root */
    1236           dnode = area_dnode(&base[3], tenured_low);
    1237           if (dnode < tenured_dnodes) {
    1238             clr_bit(refbits, dnode);
    1239           }
    1240         }
    1241         else {
    1242           base[1] = (LispObj)NULL;
    1243         }
    1244         this = next;
    1245       }
    1246     }
    1247     lisp_global(WEAKVLL) = (LispObj)NULL;
    1248 
     1308
     1309    init_weakvll();
    12491310
    12501311    if (GCn_ephemeral_dnodes == 0) {
     
    13881449    reap_gcable_ptrs();
    13891450
    1390     /* Restore population data refbits for forwarding */
    1391     if (GCn_ephemeral_dnodes) {
    1392       LispObj *tenured_low = (LispObj *)tenured_area->low;
    1393       natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
    1394       bitvector refbits = tenured_area->refbits;
    1395       LispObj this = lisp_global(WEAKVLL);
    1396 
    1397       while (this) {
    1398         LispObj *base = ptr_from_lispobj(this);
    1399         natural dnode = area_dnode(&base[3], tenured_low);
    1400         if (dnode < tenured_dnodes) {
    1401           if (base[3] >= GCarealow) {
    1402             set_bit(refbits, dnode);
    1403           }
    1404           // might have set termination list to a new pointer
    1405           if ((base[2] >> population_termination_bit) && (base[4] >= GCarealow)) {
    1406             set_bit(refbits, dnode+1);
    1407           }
    1408         }
    1409         this = base[1];
    1410       }
    1411     }
     1451    preforward_weakvll();
    14121452
    14131453    GCrelocptr = global_reloctab;
     
    14721512    a->active = (BytePtr) ptr_from_lispobj(compact_dynamic_heap());
    14731513
    1474     forward_weakvll();
     1514    forward_weakvll_links();
    14751515
    14761516    if (to) {
  • branches/working-0711/ccl/lisp-kernel/x86-gc.c

    r13278 r13293  
    12261226  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
    12271227  Boolean keep_x1, keep_x2;
     1228  natural hash_dnode_limit = 0;
     1229  hash_table_vector_header *hashp = NULL;
     1230  int mark_method = 3;
    12281231
    12291232  if (GCDebug) {
     
    12391242     Some headers are "interesting", to the forwarder if not to us.
    12401243
    1241      We -don't- give anything any weak treatment here.  Weak things have
    1242      to be seen by a full gc, for some value of 'full'.
    12431244     */
    12441245
     
    12861287      bits &= ~(BIT0_MASK >> bitidx);
    12871288
     1289      if (hashp) {
     1290        Boolean force_x1 = false;
     1291        if ((memo_dnode >= hash_dnode_limit) && (mark_method == 3)) {
     1292          /* if vector_header_count is odd, x1 might be the last word of the header */
     1293          force_x1 = (hash_table_vector_header_count & 1) && (memo_dnode == hash_dnode_limit);
     1294          /* was marking header, switch to data */
     1295          hash_dnode_limit = area_dnode(((LispObj *)hashp)
     1296                                        + 1
     1297                                        + header_element_count(hashp->header),
     1298                                        a->low);
     1299          /* In traditional weak method, don't mark vector entries at all. */
     1300          /* Otherwise mark the non-weak elements only */
     1301          mark_method = ((lisp_global(WEAK_GC_METHOD) == 0) ? 0 :
     1302                         ((hashp->flags & nhash_weak_value_mask)
     1303                          ? (1 + (hash_table_vector_header_count & 1))
     1304                          : (2 - (hash_table_vector_header_count & 1))));
     1305        }
     1306
     1307        if (memo_dnode < hash_dnode_limit) {
     1308          /* perhaps ignore one or both of the elements */
     1309          if (!force_x1 && !(mark_method & 1)) x1 = 0;
     1310          if (!(mark_method & 2)) x2 = 0;
     1311        } else {
     1312          hashp = NULL;
     1313        }
     1314      }
     1315
    12881316      if (header_subtag(x1) == subtag_hash_vector) {
    1289         LispObj flags = ((hash_table_vector_header *) p-2)->flags;
    1290         if (flags & nhash_weak_mask) {
    1291           *(p-1) = GCweakvll;
    1292           GCweakvll = ptr_to_lispobj(p - 2);
    1293           x2 = 0;
     1317        if (hashp) Bug(NULL, "header inside hash vector?");
     1318        hash_table_vector_header *hp = (hash_table_vector_header *)(p - 2);
     1319        if (hp->flags & nhash_weak_mask) {
     1320          /* If header_count is odd, this cuts off the last header field */
     1321          /* That case is handled specially above */
     1322          hash_dnode_limit = memo_dnode + ((hash_table_vector_header_count) >>1);
     1323          hashp = hp;
     1324          mark_method = 3;
    12941325        }
    12951326      }
     
    12981329      keep_x2 = mark_ephemeral_root(x2);
    12991330      if ((keep_x1 == false) &&
    1300           (keep_x2 == false)) {
     1331          (keep_x2 == false) &&
     1332          (hashp == NULL)) {
    13011333        outbits &= ~(BIT0_MASK >> bitidx);
    13021334      }
Note: See TracChangeset for help on using the changeset viewer.