Changeset 13330


Ignore:
Timestamp:
Dec 22, 2009, 9:58:21 PM (10 years ago)
Author:
gz
Message:

Changes in handling of weak vectors (i.e. populations and weak hash table vectors) in ephemeral gc, to allow egc to collect ephemeral objects stored in older weak vectors:

  • all tenured populations are now processed at every gc. (In normal use, population.data has newest conses at the front, and processing will terminate as soon as it reaches a cons not in the area being gc'd, so in practice this will only process cells actually added in the current generation, which should limit the performance impact)
  • the intergenerational pointers of all tenured weak hash vectors are now processed at every gc.

Details:

  • add new global WEAKVLL to store weak vectors between gc's, update it during gc.
  • initialize GCweakvll from WEAKVLL so tenured vectors are included.
  • keep the gc-link field in weak vectors untagged (i.e. tagged as a fixnum) so can control when they get forwarded.
  • when marking/reaping weak hash vectors, use refbits to skip over uninteresting entries.
  • during normal mark phase, arrange to not mark population.data even if intergen.
  • account for population.termination becoming intergen even if it wasn't before.
  • save WEAKVLL when image is saved
Location:
trunk/source
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/source

  • trunk/source/compiler/PPC/ppc-arch.lisp

    r13280 r13330  
    275275    image-name                          ; current image name
    276276    initial-tcr                         ; initial thread's context record
     277    weakvll                             ; all populations as of last GC
    277278    ))
    278279
  • trunk/source/compiler/X86/x86-arch.lisp

    r13280 r13330  
    7777    image-name                          ; current image name
    7878    initial-tcr                         ; initial thread's context record
     79    weakvll                             ; all populations as of last GC
    7980    ))
    8081
  • trunk/source/lisp-kernel/bits.h

    r13246 r13330  
    7373clr_bit(bitvector bits, natural bitnum)
    7474{
    75   unsigned
     75  natural
    7676    windex = bitnum>>bitmap_shift,
    7777    old = bits[windex],
  • trunk/source/lisp-kernel/gc-common.c

    r13279 r13330  
    196196  if (terminatablep) {
    197197    deref(weakv,1+3) = termination_list;
    198     if (termination_list != lisp_nil) {
    199       deref(weakv,1) = GCweakvll;
    200       GCweakvll = weakv;
    201     }
     198  }
     199  if (termination_list != lisp_nil) {
     200    deref(weakv,1) = GCweakvll;
     201    GCweakvll = untag(weakv);
     202  } else {
     203    deref(weakv,1) = lisp_global(WEAKVLL);
     204    lisp_global(WEAKVLL) = untag(weakv);
    202205  }
    203206}
     
    213216    *hashp = (hash_table_vector_header *) ptr_from_lispobj(untag(hashv));
    214217  natural
    215     dnode,
     218    dnode;
     219  signed_natural
    216220    npairs = (header_element_count(hashp->header) -
    217221              (hash_table_vector_header_count -1)) >> 1;
    218222  LispObj *pairp = (LispObj*) (hashp+1), weakelement;
    219   Boolean
    220     weak_on_value = ((hashp->flags & nhash_weak_value_mask) != 0);
     223  int weak_index = (((hashp->flags & nhash_weak_value_mask) == 0) ? 0 : 1);
    221224  Boolean
    222225    keys_frozen = ((hashp->flags & nhash_keys_frozen_mask) != 0);
     
    224227  int tag;
    225228
    226   while (npairs--) {
    227     if (weak_on_value) {
    228       weakelement = pairp[1];
    229     } else {
    230       weakelement = pairp[0];
    231     }
     229  natural *tenured_low = (LispObj *)tenured_area->low;
     230  natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
     231  natural memo_dnode = area_dnode(ptr_to_lispobj(pairp+weak_index), tenured_low);
     232  Boolean
     233    hashv_tenured = (memo_dnode < tenured_dnodes);
     234  natural bits, bitidx, *bitsp;
     235
     236  if (hashv_tenured) {
     237    set_bitidx_vars(tenured_area->refbits, memo_dnode, bitsp, bits, bitidx);
     238  }
     239
     240  while (true) {
     241    if (hashv_tenured) {
     242      while (bits == 0) {
     243        int skip = nbits_in_word - bitidx;
     244        npairs -= skip;
     245        if (npairs <= 0) break;
     246        pairp += (skip+skip);
     247        bitidx = 0;
     248        bits = *++bitsp;
     249      }
     250      if (bits != 0) {
     251        int skip = (count_leading_zeros(bits) - bitidx);
     252        if (skip != 0) {
     253          npairs -= skip;
     254          pairp += (skip+skip);
     255          bitidx += skip;
     256        }
     257      }
     258    }
     259
     260    if (npairs <= 0) break;
     261
     262    weakelement = pairp[weak_index];
    232263    tag = fulltag_of(weakelement);
    233264    if (is_node_fulltag(tag)) {
     
    248279    }
    249280    pairp += 2;
    250   }
     281    --npairs;
     282  }
     283  deref(hashv, 1) = lisp_global(WEAKVLL);
     284  lisp_global(WEAKVLL) = untag(hashv);
    251285}
    252286
     
    256290  /* Do nothing, just add htabv to GCweakvll */
    257291  LispObj *base = (LispObj *) ptr_from_lispobj(untag(htabv));
    258  
    259   deref(base,1) = GCweakvll;
    260   GCweakvll = htabv;
     292
     293  base[1] = GCweakvll;
     294  GCweakvll = ptr_to_lispobj(base);
    261295}
    262296
     
    265299{
    266300  /* Do nothing, just add htabv to GCdwsweakvll */
     301  deref(htabv,1) = GCdwsweakvll;
     302  GCdwsweakvll = htabv;
     303}
     304
     305void
     306traditional_mark_weak_htabv(LispObj htabv)
     307{
     308  int i, skip = hash_table_vector_header_count;;
    267309  LispObj *base = (LispObj *) ptr_from_lispobj(untag(htabv));
    268  
    269   deref(base,1) = GCdwsweakvll;
    270   GCdwsweakvll = htabv;
    271 }
    272 
    273 void
    274 traditional_mark_weak_htabv(LispObj htabv)
    275 {
    276   int i, skip = hash_table_vector_header_count;;
    277310
    278311  for (i = 2; i <= skip; i++) {
    279     rmark(deref(htabv,i));
    280   }
    281 
    282   deref(htabv,1) = GCweakvll;
    283   GCweakvll = htabv;
     312    rmark(base[i]);
     313  }
     314  base[1] = GCweakvll;
     315  GCweakvll = ptr_to_lispobj(base);
    284316}
    285317
     
    309341    pairp += 2;
    310342  }
    311 
    312   deref(htabv,1) = GCweakvll;
    313   GCweakvll = htabv;
     343  deref(htabv,1)  = GCweakvll;
     344  GCweakvll = (LispObj)untag(htabv);
    314345}
    315346
     
    318349mark_weak_hash_vector(hash_table_vector_header *hashp, natural elements)
    319350{
    320   natural flags = hashp->flags, key_dnode, val_dnode;
     351  natural flags = hashp->flags, weak_dnode, nonweak_dnode;
    321352  Boolean
    322353    marked_new = false,
    323     key_marked,
    324     val_marked,
    325     weak_value = ((flags & nhash_weak_value_mask) != 0);
     354    weak_marked;
     355  int non_weak_index = (((flags & nhash_weak_value_mask) != 0) ? 0 : 1);
    326356  int
    327357    skip = hash_table_vector_header_count-1,
    328     key_tag,
    329     val_tag,
     358    weak_tag,
     359    nonweak_tag,
    330360    i;
     361  signed_natural
     362    npairs = (elements - skip) >> 1;
    331363  LispObj
    332364    *pairp = (LispObj*) (hashp+1),
    333     key,
    334     val;
     365    weak,
     366    nonweak;
     367
     368  natural *tenured_low = (LispObj *)tenured_area->low;
     369  natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
     370  natural memo_dnode = area_dnode(ptr_to_lispobj(pairp+non_weak_index), tenured_low);
     371  Boolean hashv_tenured = (memo_dnode < tenured_dnodes);
     372  natural bits, bitidx, *bitsp;
     373
     374  if (hashv_tenured) {
     375    set_bitidx_vars(tenured_area->refbits, memo_dnode, bitsp, bits, bitidx);
     376  }
    335377
    336378  /* Mark everything in the header */
     
    340382  }
    341383
    342   elements -= skip;
    343 
    344   for (i = 0; i<elements; i+=2, pairp+=2) {
    345     key = pairp[0];
    346     val = pairp[1];
    347     key_marked = val_marked = true;
    348     key_tag = fulltag_of(key);
    349     val_tag = fulltag_of(val);
    350     if (is_node_fulltag(key_tag)) {
    351       key_dnode = gc_area_dnode(key);
    352       if ((key_dnode < GCndnodes_in_area) &&
    353           ! ref_bit(GCmarkbits,key_dnode)) {
    354         key_marked = false;
    355       }
    356     }
    357     if (is_node_fulltag(val_tag)) {
    358       val_dnode = gc_area_dnode(val);
    359       if ((val_dnode < GCndnodes_in_area) &&
    360           ! ref_bit(GCmarkbits,val_dnode)) {
    361         val_marked = false;
    362       }
    363     }
    364 
    365     if (weak_value) {
    366       if (val_marked & !key_marked) {
    367         mark_root(key);
    368         marked_new = true;
    369       }
    370     } else {
    371       if (key_marked & !val_marked) {
    372         mark_root(val);
    373         marked_new = true;
    374       }
    375     }
     384  while (true) {
     385    if (hashv_tenured) {
     386      while (bits == 0) {
     387        int skip = nbits_in_word - bitidx;
     388        npairs -= skip;
     389        if (npairs <= 0) break;
     390        pairp += (skip+skip);
     391        bitidx = 0;
     392        bits = *++bitsp;
     393      }
     394      if (bits != 0) {
     395        int skip = count_leading_zeros(bits) - bitidx;
     396        if (skip != 0) {
     397          npairs -= skip;
     398          pairp += (skip+skip);
     399          bitidx += skip;
     400        }
     401      }
     402    }
     403    if (npairs <= 0) break;
     404
     405    nonweak = pairp[non_weak_index];
     406    weak = pairp[1-non_weak_index];
     407
     408    nonweak_tag = fulltag_of(nonweak);
     409    if (is_node_fulltag(nonweak_tag)) {
     410      nonweak_dnode = gc_area_dnode(nonweak);
     411      if ((nonweak_dnode < GCndnodes_in_area) &&
     412          ! ref_bit(GCmarkbits,nonweak_dnode)) {
     413        weak_marked = true;
     414        weak_tag = fulltag_of(weak);
     415        if (is_node_fulltag(weak_tag)) {
     416          weak_dnode = gc_area_dnode(weak);
     417          if ((weak_dnode < GCndnodes_in_area) &&
     418              ! ref_bit(GCmarkbits, weak_dnode)) {
     419            weak_marked = false;
     420          }
     421        }
     422        if (weak_marked) {
     423          mark_root(nonweak);
     424          marked_new = true;
     425        }
     426      }
     427    }
     428
     429    pairp+=2;
     430    --npairs;
    376431  }
    377432  return marked_new;
     
    427482 
    428483void
     484mark_termination_lists()
     485{
     486  /*
     487     Mark the termination lists in all terminatable weak vectors, which
     488     are now linked together on GCweakvll, and add them to WEAKVLL,
     489     which already contains all other weak vectors.
     490  */
     491  LispObj pending = GCweakvll,
     492          *base = (LispObj *)NULL;
     493
     494  while (pending) {
     495    base = ptr_from_lispobj(pending);
     496    pending = base[1];
     497
     498    mark_root(base[1+3]);
     499  }
     500  if (base) {
     501    base[1] = lisp_global(WEAKVLL);
     502    lisp_global(WEAKVLL) = GCweakvll;
     503  }
     504
     505}
     506
     507
     508void
    429509traditional_markhtabvs()
    430510{
    431   LispObj this, header, pending;
     511  LispObj *base, this, header, pending;
    432512  int subtag;
    433513  hash_table_vector_header *hashp;
     
    439519   
    440520    while (GCweakvll) {
    441       this = GCweakvll;
    442       GCweakvll = deref(this,1);
     521      base = ptr_from_lispobj(GCweakvll);
     522      GCweakvll = base[1];
    443523     
    444       header = header_of(this);
     524      header = base[0];
    445525      subtag = header_subtag(header);
    446526     
    447527      if (subtag == subtag_weak) {
    448         natural weak_type = deref(this,2);
    449         deref(this,1) = pending;
    450         pending = this;
     528        natural weak_type = base[2];
     529        this = ptr_to_lispobj(base) + fulltag_misc;
     530        base[1] = pending;
     531        pending = ptr_to_lispobj(base);
    451532        if ((weak_type & population_type_mask) == population_weak_alist) {
    452533          if (mark_weak_alist(this, weak_type)) {
     
    457538        natural elements = header_element_count(header);
    458539
    459         hashp = (hash_table_vector_header *) ptr_from_lispobj(untag(this));
     540        hashp = (hash_table_vector_header *) base;
    460541        if (hashp->flags & nhash_weak_mask) {
    461           deref(this,1) = pending;
    462           pending = this;
     542          base[1] = pending;
     543          pending = ptr_to_lispobj(base);
    463544          if (mark_weak_hash_vector(hashp, elements)) {
    464545            marked_new = true;
     
    466547        }
    467548      } else {
    468         Bug(NULL, "Strange object on weak vector linked list: 0x~08x\n", this);
     549        Bug(NULL, "Strange object on weak vector linked list: " LISP "\n", base);
    469550      }
    470551    }
     
    481562
    482563  while (pending) {
    483     this = pending;
    484     pending = deref(this,1);
    485     deref(this,1) = (LispObj)NULL;
    486 
    487     subtag = header_subtag(header_of(this));
     564    base = ptr_from_lispobj(pending);
     565    pending = base[1];
     566    base[1] = (LispObj)NULL;
     567
     568    this = ptr_to_lispobj(base) + fulltag_misc;
     569
     570    subtag = header_subtag(base[0]);
    488571    if (subtag == subtag_weak) {
    489572      reapweakv(this);
     
    492575    }
    493576  }
    494 
    495   /* Finally, mark the termination lists in all terminatable weak vectors
    496      They are now linked together on GCweakvll.
    497      This is where to store  lisp_global(TERMINATION_LIST) if we decide to do that,
    498      but it will force terminatable popualations to hold on to each other
    499      (set TERMINATION_LIST before clearing GCweakvll, and don't clear deref(this,1)).
    500      */
    501   pending = GCweakvll;
    502   GCweakvll = (LispObj)NULL;
    503   while (pending) {
    504     this = pending;
    505     pending = deref(this,1);
    506     deref(this,1) = (LispObj)NULL;
    507     mark_root(deref(this,1+3));
    508   }
     577  mark_termination_lists();
    509578}
    510579
     
    512581ncircle_markhtabvs()
    513582{
    514   LispObj this, header, pending = 0;
     583  LispObj *base, this, header, pending = 0;
    515584  int subtag;
    516   Boolean marked_new;
    517585
    518586  /* First, process any weak hash tables that may have
     
    527595
    528596  while (GCweakvll) {
    529     this = GCweakvll;
    530     GCweakvll = deref(this,1);
    531      
    532     header = header_of(this);
     597    base = ptr_from_lispobj(GCweakvll);
     598    GCweakvll = base[1];
     599    base[1] = (LispObj)NULL;
     600
     601    this = ptr_to_lispobj(base) + fulltag_misc;
     602
     603    header = base[0];
    533604    subtag = header_subtag(header);
    534605     
    535606    if (subtag == subtag_weak) {
    536       natural weak_type = deref(this,2);
    537       deref(this,1) = pending;
    538       pending = this;
     607      natural weak_type = base[2];
     608      base[1] = pending;
     609      pending = ptr_to_lispobj(base);
    539610      if ((weak_type & population_type_mask) == population_weak_alist) {
    540         if (mark_weak_alist(this, weak_type)) {
    541           marked_new = true;
    542           }
     611        mark_weak_alist(this, weak_type);
    543612      }
    544613    } else if (subtag == subtag_hash_vector) {
     
    553622
    554623  while (pending) {
    555     this = pending;
    556     pending = deref(this,1);
    557     deref(this,1) = (LispObj)NULL;
    558 
    559     subtag = header_subtag(header_of(this));
     624    base = ptr_from_lispobj(pending);
     625    pending = base[1];
     626    base[1] = (LispObj)NULL;
     627
     628    this = ptr_to_lispobj(base) + fulltag_misc;
     629
     630    subtag = header_subtag(base[0]);
    560631    if (subtag == subtag_weak) {
    561632      reapweakv(this);
     
    565636  }
    566637
    567   /* Finally, mark the termination lists in all terminatable weak vectors
    568      They are now linked together on GCweakvll.
    569      This is where to store  lisp_global(TERMINATION_LIST) if we decide to do that,
    570      but it will force terminatable popualations to hold on to each other
    571      (set TERMINATION_LIST before clearing GCweakvll, and don't clear deref(this,1)).
    572      */
    573   pending = GCweakvll;
    574   GCweakvll = (LispObj)NULL;
    575   while (pending) {
    576     this = pending;
    577     pending = deref(this,1);
    578     deref(this,1) = (LispObj)NULL;
    579     mark_root(deref(this,1+3));
    580   }
     638  mark_termination_lists();
    581639}
    582640
     
    846904}
    847905
     906void
     907init_weakvll ()
     908{
     909  LispObj this = lisp_global(WEAKVLL); /* all weak vectors as of last gc */
     910
     911  GCweakvll = (LispObj)NULL;
     912  lisp_global(WEAKVLL) = (LispObj)NULL;
     913
     914  if (GCn_ephemeral_dnodes) {
     915    /* For egc case, initialize GCweakvll with weak vectors not in the
     916       GC area.  Weak vectors in the GC area will be added during marking.
     917    */
     918
     919    LispObj *tenured_low = (LispObj *)tenured_area->low;
     920    natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
     921    bitvector refbits = tenured_area->refbits;
     922
     923    while (this) {
     924      LispObj *base = ptr_from_lispobj(this);
     925      LispObj next = base[1];
     926      natural dnode = gc_dynamic_area_dnode(this);
     927      if (dnode < GCndynamic_dnodes_in_area) {
     928        base[1] = (LispObj)NULL; /* drop it, might be garbage */
     929      } else {
     930        base[1] = GCweakvll;
     931        GCweakvll = ptr_to_lispobj(base);
     932        if (header_subtag(base[0]) == subtag_weak) {
     933          dnode = area_dnode(&base[3], tenured_low);
     934          if (dnode < tenured_dnodes) {
     935            clr_bit(refbits, dnode); /* Don't treat population.data as root */
     936          }
     937        } else {
     938          if (header_subtag(base[0]) != subtag_hash_vector)
     939            Bug(NULL, "Unexpected entry " LISP " -> " LISP " on WEAKVLL", base, base[0]);
     940          dnode = area_dnode(base, tenured_low);
     941          if ((dnode < tenured_dnodes) && !ref_bit(refbits, dnode)) {
     942            Boolean drop = true;
     943            /* hash vectors get marked headers if they have any ephemeral keys */
     944            /* but not if they have ephemeral values. */
     945            if (((hash_table_vector_header *)base)->flags & nhash_weak_value_mask) {
     946              signed_natural count = (header_element_count(base[0]) + 2) >> 1;
     947              natural bits, bitidx, *bitsp;
     948              set_bitidx_vars(refbits, dnode, bitsp, bits, bitidx);
     949              while ((0 < count) && (bits == 0)) {
     950                int skip = nbits_in_word - bitidx;
     951                count -= skip;
     952                bits = *++bitsp;
     953                bitidx = 0;
     954              }
     955              count -=  (count_leading_zeros(bits) - bitidx);
     956
     957              if (0 < count) {
     958                set_bit(refbits, dnode); /* has ephemeral values, mark header */
     959                drop = false;
     960              }
     961            }
     962            if (drop) { /* if nothing ephemeral, drop it from GCweakvll. */
     963              GCweakvll = base[1];
     964              base[1] = lisp_global(WEAKVLL);
     965              lisp_global(WEAKVLL) = ptr_to_lispobj(base);
     966            }
     967          }
     968        }
     969      }
     970      this = next;
     971    }
     972  }
     973}
     974
     975 
     976void
     977preforward_weakvll ()
     978{
     979  /* reset population refbits for forwarding */
     980  if (GCn_ephemeral_dnodes) {
     981    LispObj this = lisp_global(WEAKVLL);
     982    LispObj *tenured_low = (LispObj *)tenured_area->low;
     983    natural tenured_dnodes = area_dnode(GCarealow, tenured_low);
     984    bitvector refbits = tenured_area->refbits;
     985
     986    while (this) {
     987      LispObj *base = ptr_from_lispobj(this);
     988      if (header_subtag(base[0]) == subtag_weak) {
     989        natural dnode = area_dnode(&base[3], tenured_low);
     990        if (base[3] >= GCarealow) {
     991          if (dnode < tenured_dnodes) {
     992            set_bit(refbits, dnode);
     993          }
     994        }
     995        /* might have set termination list to a new pointer */
     996        if ((base[2] >> population_termination_bit) && (base[4] >= GCarealow)) {
     997          if ((dnode + 1) < tenured_dnodes) {
     998            set_bit(refbits, dnode+1);
     999          }
     1000        }
     1001      }
     1002      this = base[1];
     1003    }
     1004  }
     1005}
     1006
     1007
     1008void
     1009forward_weakvll_links()
     1010{
     1011  LispObj *ptr = &(lisp_global(WEAKVLL)), this, new, old;
     1012
     1013  while (this = *ptr) {
     1014    old = this + fulltag_misc;
     1015    new = node_forwarding_address(old);
     1016    if (old != new) {
     1017      *ptr = untag(new);
     1018    }
     1019    ptr = &(deref(new,1));
     1020  }
     1021}
     1022
     1023
     1024
     1025
     1026
    8481027LispObj
    8491028node_forwarding_address(LispObj node)
     
    11711350  TCR *other_tcr;
    11721351  natural static_dnodes;
    1173 
    1174   install_weak_mark_functions(lisp_global(WEAK_GC_METHOD) >> fixnumshift);
    1175  
     1352  natural weak_method = lisp_global(WEAK_GC_METHOD) >> fixnumshift;
     1353
    11761354#ifndef FORCE_DWS_MARK
    11771355  if ((natural) (tcr->cs_limit) == CS_OVERFLOW_FORCE_LIMIT) {
     
    12171395  }
    12181396
     1397  install_weak_mark_functions(weak_method);
     1398 
    12191399  if (GCverbose) {
    12201400    char buf[16];
     
    12641444
    12651445    zero_bits(GCmarkbits, GCndnodes_in_area);
    1266     GCweakvll = (LispObj)NULL;
     1446
     1447    init_weakvll();
    12671448
    12681449    if (GCn_ephemeral_dnodes == 0) {
     
    13291510    }
    13301511 
    1331     if (lisp_global(OLDEST_EPHEMERAL)) {
     1512    if (GCephemeral_low) {
    13321513      mark_memoized_area(tenured_area, area_dnode(a->low,tenured_area->low));
    13331514    }
     
    14081589    reap_gcable_ptrs();
    14091590
     1591    preforward_weakvll();
     1592
    14101593    GCrelocptr = global_reloctab;
    14111594    GCfirstunmarked = calculate_relocation();
     
    14691652    forward_memoized_area(managed_static_area,area_dnode(managed_static_area->active,managed_static_area->low));
    14701653    a->active = (BytePtr) ptr_from_lispobj(compact_dynamic_heap());
     1654
     1655    forward_weakvll_links();
     1656
    14711657    if (to) {
    14721658      tenure_to_area(to);
  • trunk/source/lisp-kernel/image.c

    r13279 r13330  
    8080      }
    8181#endif
    82 
     82      if (header_subtag(w0) == subtag_weak) {
     83        LispObj link = start[1];
     84        if ((link >= low) && (link < high)) {
     85          start[1] = (link+bias);
     86        }
     87      }
    8388      if ((w0 >= low) && (w0 < high) &&
    8489          ((1<<fulltag) & RELOCATABLE_FULLTAG_MASK)) {
     
    562567    case G2_THRESHOLD:
    563568      break;
     569    case WEAKVLL:
     570      break;
    564571    default:
    565572      lisp_global(i) = 0;
  • trunk/source/lisp-kernel/lisp_globals.h

    r13279 r13330  
    7070#define IMAGE_NAME (-47)        /* --image-name arg */
    7171#define INITIAL_TCR (-48)       /* initial thread tcr */
     72#define WEAKVLL (-49)           /* all populations as of last GC */
    7273
    73 #define MIN_KERNEL_GLOBAL INITIAL_TCR
     74#define MIN_KERNEL_GLOBAL WEAKVLL
    7475
    7576/* These are only non-zero when an image is being saved or loaded */
  • trunk/source/lisp-kernel/ppc-constants.s

    r13279 r13330  
    184184])
    185185
    186 num_lisp_globals = 48            /* MUST UPDATE THIS !!! */
     186num_lisp_globals = 49            /* MUST UPDATE THIS !!! */
    187187       
    188188        _struct(lisp_globals,lisp_globals_limit-(num_lisp_globals*node_size))
     189         _node(weakvll)                 /* all populations as of last GC */
    189190         _node(initial_tcr)             /* initial thread tcr */
    190191         _node(image_name)              /* --image-name argument */
  • trunk/source/lisp-kernel/ppc-gc.c

    r13295 r13330  
    216216
    217217/* Sooner or later, this probably wants to be in assembler */
    218 /* Return false if n is definitely not an ephemeral node, true if
    219    it might be */
    220218void
    221219mark_root(LispObj n)
     
    310308
    311309      if (subtag == subtag_pool) {
    312         deref(ptr_to_lispobj(base), 1) = lisp_nil;
     310        deref(n, 1) = lisp_nil;
    313311      }
    314312     
     
    329327      }
    330328      if (subtag == subtag_weak) {
    331         deref(ptr_to_lispobj(base),1) = GCweakvll;
    332         GCweakvll = n;
     329        deref(n, 1) = GCweakvll;
     330        GCweakvll = untag(n);
    333331      }
    334332    }
     
    606604      if (subtag == subtag_weak) {
    607605        deref(n, 1) = GCweakvll;
    608         GCweakvll = n;
     606        GCweakvll = untag(n);
    609607      }
    610608
     
    798796    if (header_subtag(next) == subtag_weak) {
    799797      deref(this, 1) = GCweakvll;
    800       GCweakvll = this;
     798      GCweakvll = untag(this);
    801799    }
    802800    goto Climb;
     
    886884        ref_dnode = area_dnode(start, base);
    887885        if (!ref_bit(refbits, ref_dnode)) {
    888           Bug(NULL, "Missing memoization in doublenode at 0x" LISP, start);
     886          Bug(NULL, "Missing memoization in doublenode at 0x" LISP "\n", start);
    889887          set_bit(refbits, ref_dnode);
    890888        }
     
    904902  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
    905903  Boolean keep_x1, keep_x2;
     904  natural hash_dnode_limit = 0;
     905  hash_table_vector_header *hashp = NULL;
     906  int mark_method = 3;
    906907
    907908  if (GCDebug) {
     
    917918     Some headers are "interesting", to the forwarder if not to us.
    918919
    919      We -don't- give anything any weak treatment here.  Weak things have
    920      to be seen by a full gc, for some value of 'full'.
    921920     */
    922921
     
    963962      x2 = *p++;
    964963      bits &= ~(BIT0_MASK >> bitidx);
     964
     965      if (hashp) {
     966        Boolean force_x1 = false;
     967        if ((memo_dnode >= hash_dnode_limit) && (mark_method == 3)) {
     968          /* if vector_header_count is odd, x1 might be the last word of the header */
     969          force_x1 = (hash_table_vector_header_count & 1) && (memo_dnode == hash_dnode_limit);
     970          /* was marking header, switch to data */
     971          hash_dnode_limit = area_dnode(((LispObj *)hashp)
     972                                        + 1
     973                                        + header_element_count(hashp->header),
     974                                        a->low);
     975          /* In traditional weak method, don't mark vector entries at all. */
     976          /* Otherwise mark the non-weak elements only */
     977          mark_method = ((lisp_global(WEAK_GC_METHOD) == 0) ? 0 :
     978                         ((hashp->flags & nhash_weak_value_mask)
     979                          ? (1 + (hash_table_vector_header_count & 1))
     980                          : (2 - (hash_table_vector_header_count & 1))));
     981        }
     982
     983        if (memo_dnode < hash_dnode_limit) {
     984          /* perhaps ignore one or both of the elements */
     985          if (!force_x1 && !(mark_method & 1)) x1 = 0;
     986          if (!(mark_method & 2)) x2 = 0;
     987        } else {
     988          hashp = NULL;
     989        }
     990      }
     991
     992      if (header_subtag(x1) == subtag_hash_vector) {
     993        if (hashp) Bug(NULL, "header inside hash vector?");
     994        hash_table_vector_header *hp = (hash_table_vector_header *)(p - 2);
     995        if (hp->flags & nhash_weak_mask) {
     996          /* If header_count is odd, this cuts off the last header field */
     997          /* That case is handled specially above */
     998          hash_dnode_limit = memo_dnode + ((hash_table_vector_header_count) >>1);
     999          hashp = hp;
     1000          mark_method = 3;
     1001        }
     1002      }
     1003
    9651004      keep_x1 = mark_ephemeral_root(x1);
    9661005      keep_x2 = mark_ephemeral_root(x2);
    9671006      if ((keep_x1 == false) &&
    968           (keep_x2 == false)) {
     1007          (keep_x2 == false) &&
     1008          (hashp == NULL)) {
    9691009        outbits &= ~(BIT0_MASK >> bitidx);
    9701010      }
     
    10221062          element_count -= 1;
    10231063        start[1] = GCweakvll;
    1024         GCweakvll = (LispObj) (((natural) start) + fulltag_misc);   
     1064        GCweakvll = ptr_to_lispobj(start);
    10251065      }
    10261066
  • trunk/source/lisp-kernel/x86-constants.s

    r13279 r13330  
    6666define([seen_aok_bit],[28])       
    6767       
    68 num_lisp_globals = 48            /* MUST UPDATE THIS !!!   */
     68num_lisp_globals = 49            /* MUST UPDATE THIS !!!   */
    6969       
    7070        _struct(lisp_globals,lisp_globals_limit-(num_lisp_globals*node_size))
     71         _node(weakvll)                 /* all populations as of last GC */
    7172         _node(initial_tcr)             /* initial thread tcr */
    7273         _node(image_name)              /* --image-name argument */
  • trunk/source/lisp-kernel/x86-gc.c

    r13295 r13330  
    390390
    391391/* Sooner or later, this probably wants to be in assembler */
    392 /* Return false if n is definitely not an ephemeral node, true if
    393    it might be */
    394392void
    395393mark_root(LispObj n)
     
    530528
    531529      if (subtag == subtag_pool) {
    532         deref(base, 1) = lisp_nil;
     530        deref(n, 1) = lisp_nil;
    533531      }
    534532     
     
    564562      }
    565563      if (subtag == subtag_weak) {
    566         deref(ptr_to_lispobj(base),1) = GCweakvll;
    567         GCweakvll = n;
     564        deref(n, 1) = GCweakvll;
     565        GCweakvll = untag(n);
    568566      }
    569567    }
     
    774772      if (subtag == subtag_weak) {
    775773        deref(n, 1) = GCweakvll;
    776         GCweakvll = n;
     774        GCweakvll = untag(n);
    777775      }
    778776
     
    10971095    if (header_subtag(next) == subtag_weak) {
    10981096      deref(this, 1) = GCweakvll;
    1099       GCweakvll = this;
     1097      GCweakvll = untag(this);
    11001098    }
    11011099    goto Climb;
     
    12071205        ref_dnode = area_dnode(start, base);
    12081206        if (!ref_bit(refbits, ref_dnode)) {
    1209           Bug(NULL, "Missing memoization in doublenode at 0x" LISP, start);
     1207          Bug(NULL, "Missing memoization in doublenode at 0x" LISP "\n", start);
    12101208          set_bit(refbits, ref_dnode);
    12111209        }
     
    12281226  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0;
    12291227  Boolean keep_x1, keep_x2;
     1228  natural hash_dnode_limit = 0;
     1229  hash_table_vector_header *hashp = NULL;
     1230  int mark_method = 3;
    12301231
    12311232  if (GCDebug) {
     
    12411242     Some headers are "interesting", to the forwarder if not to us.
    12421243
    1243      We -don't- give anything any weak treatment here.  Weak things have
    1244      to be seen by a full gc, for some value of 'full'.
    12451244     */
    12461245
     
    12871286      x2 = *p++;
    12881287      bits &= ~(BIT0_MASK >> bitidx);
     1288
     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
     1316      if (header_subtag(x1) == subtag_hash_vector) {
     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;
     1325        }
     1326      }
     1327
    12891328      keep_x1 = mark_ephemeral_root(x1);
    12901329      keep_x2 = mark_ephemeral_root(x2);
    12911330      if ((keep_x1 == false) &&
    1292           (keep_x2 == false)) {
     1331          (keep_x2 == false) &&
     1332          (hashp == NULL)) {
    12931333        outbits &= ~(BIT0_MASK >> bitidx);
    12941334      }
     
    13521392          element_count -= 1;
    13531393        start[1] = GCweakvll;
    1354         GCweakvll = (LispObj) (((natural) start) + fulltag_misc);   
     1394        GCweakvll = ptr_to_lispobj(start);
    13551395      }
    13561396
Note: See TracChangeset for help on using the changeset viewer.