Changeset 13042


Ignore:
Timestamp:
Oct 18, 2009, 10:32:28 PM (10 years ago)
Author:
gb
Message:

A function-purified lisp survived a GC; Miller time.

TODO: method-functions keep a backpointer to the containing GF in their
names, so adding/removing a method from a GF can cause writes to the
method-function's immediates. We generally assume that most functions
have immutable immediates, and we may need to think about this some more.

TODO: things that're referenced as purified function constants are copied
from dynamic space to a new(ly-used) "managed" (growable) static area. A
fairly high percentage of those mutable static things still refer to the
dynamic area - often to a fairly small number of things in the dynamic
area. We shallow-copy PACKAGE objects and the undefined function object,
but there may be more opportunities to reduce the number of static-to-dynamic
references. (We use a bitmap to track those refences and the bitmap seems
to be about 10% full; my intuition is that it should ideally be more sparse
than that.)

TODO: new static cons allocation and GC.

TODO: see if this even builds anywhere but on x86-64 Darwin.

TODO: see how other things that walk the area list (watch/unwatch) are

affected by the new scheme.

l0-hash.lisp, l0-symbol.lisp: change the way that a symbol's hash code

and plist are packed into the nominal symbol.plist-cell slot. If a symbol
contains a fixnum hash code and a null plist (as seems common), the slot
contains just the fixnum. (This is intended to reduce the number of
static->dynamic references from symbols.)

gc-common.c, gc.h, image.c, lisp_globals.h, memory.c, pmcl_kernel.c, ppc-constants.s, x86-constants.s, x86-exceptions.c, x86-gc.c, x86-spentry64.s: lots of changes to promote x86 function purification, at least on x8664.

Location:
branches/purify/source
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • branches/purify/source/level-0/l0-hash.lisp

    r11958 r13042  
    175175  (if sym   
    176176    (let* ((vector (%symptr->symvector sym))
    177            (cell (%svref vector target::symbol.plist-cell)))
    178       (or (car cell)
     177           (cell (%svref vector target::symbol.plist-cell))
     178           (consp (consp cell)))
     179      (or (if consp (%car cell) cell)
    179180          (let* ((pname (%svref vector target::symbol.pname-cell))
    180181                 (hash (mixup-hash-code (%pname-hash pname (uvsize pname)))))
    181             (declare (type simple-string pname))
    182             (if cell
    183               (setf (car cell) hash)
    184               (progn
    185                 (setf (%svref vector target::symbol.plist-cell)
    186                       (cons hash nil))
    187                 hash)))))
     182            (declare (type simple-string pname) (fixnum hash))
     183            (if consp
     184              (setf (%car cell) hash)
     185              (setf (%svref vector target::symbol.plist-cell) hash)))))
    188186    +nil-hash+))
    189187             
  • branches/purify/source/level-0/l0-symbol.lisp

    r10150 r13042  
    5353        (error "Bad plist: ~s" plist))))
    5454  (let* ((vector (symptr->symvector (%symbol->symptr sym)))
    55          (cell (%svref vector target::symbol.plist-cell)))
     55         (cell (%svref vector target::symbol.plist-cell))
     56         (consp (consp cell)))
    5657    (if plist
    57       (if (consp cell)
     58      (if consp
    5859        (setf (cdr cell) plist)
    5960        (cdr (setf (%svref vector target::symbol.plist-cell) (cons nil plist))))
    60       (if (car cell)
    61         (setf (cdr cell) nil)
    62         (if cell (setf (cdr cell) nil))))))
     61      (progn
     62        (if consp
     63          (setf (%svref vector target::symbol.plist-cell) (%car cell)))
     64        nil))))
    6365
    6466
     
    7981(defun symbol-plist (sym)
    8082  "Return SYMBOL's property list."
    81   (cdr (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.plist-cell)))
     83  (let* ((cell (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.plist-cell)))
     84    (if (consp cell)
     85      (cdr cell))))
    8286
    8387
     
    8589  "Look on the property list of SYMBOL for the specified INDICATOR. If this
    8690  is found, return the associated value, else return DEFAULT."
    87   (let* ((tail (%pl-search
    88                 (cdr (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.plist-cell)) key)))
     91  (let* ((cell (%svref (symptr->symvector (%symbol->symptr sym)) target::symbol.plist-cell))
     92         (tail (if (consp cell)
     93                 (%pl-search (cdr cell ) key))))
    8994    (if tail (%cadr tail) default)))
    9095
     
    9398         (vector (symptr->symvector symptr))
    9499         (cell  (%svref vector target::symbol.plist-cell))
    95          (plist (cdr cell))
     100         (plist (if (consp cell) (cdr cell)))
    96101         (tail (%pl-search plist key)))
    97102    (if tail
     
    99104      (progn
    100105        (setq plist (cons key (cons value plist)))
    101         (if cell
     106        (if (consp cell)
    102107          (setf (cdr cell) plist)
    103108          (setf (%svref vector target::symbol.plist-cell) (cons nil plist)))))
  • branches/purify/source/lisp-kernel/area.h

    r12895 r13042  
    213213extern BytePtr static_space_start, static_space_active, static_space_limit;
    214214extern area *find_readonly_area(void);
     215extern BytePtr low_relocatable_address, high_relocatable_address,
     216  low_markable_address, high_markable_address;
    215217
    216218#endif /* __AREA_H__ */
  • branches/purify/source/lisp-kernel/gc-common.c

    r12810 r13042  
    923923  Boolean header_p;
    924924
    925   if (GCDebug) {
    926     check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
    927   }
    928 
    929   /* This is pretty straightforward, but we have to note
    930      when we move a key in a hash table vector that wants
    931      us to tell it about that. */
    932 
    933   set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
    934   while (memo_dnode < num_memo_dnodes) {
    935     if (bits == 0) {
    936       int remain = nbits_in_word - bitidx;
    937       memo_dnode += remain;
    938       p += (remain+remain);
    939       bits = *++bitsp;
    940       bitidx = 0;
    941     } else {
    942       nextbit = count_leading_zeros(bits);
    943       if ((diff = (nextbit - bitidx)) != 0) {
    944         memo_dnode += diff;
    945         bitidx = nextbit;
    946         p += (diff+diff);
    947       }
    948       x1 = p[0];
    949       x2 = p[1];
    950       tag_x1 = fulltag_of(x1);
    951       bits &= ~(BIT0_MASK >> bitidx);
    952       header_p = (nodeheader_tag_p(tag_x1));
    953 
    954       if (header_p &&
    955           (header_subtag(x1) == subtag_hash_vector)) {
    956         hashp = (hash_table_vector_header *) p;
    957         if (hashp->flags & nhash_track_keys_mask) {
    958           hash_dnode_limit = memo_dnode + ((header_element_count(x1)+2)>>1);
    959         } else {
    960           hashp = NULL;
    961         }
    962       }
    963 
    964 
    965       if (! header_p) {
    966         new = node_forwarding_address(x1);
    967         if (new != x1) {
     925  if (num_memo_dnodes) {
     926    if (GCDebug) {
     927      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
     928    }
     929
     930    /* This is pretty straightforward, but we have to note
     931       when we move a key in a hash table vector that wants
     932       us to tell it about that. */
     933
     934    set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
     935    while (memo_dnode < num_memo_dnodes) {
     936      if (bits == 0) {
     937        int remain = nbits_in_word - bitidx;
     938        memo_dnode += remain;
     939        p += (remain+remain);
     940        bits = *++bitsp;
     941        bitidx = 0;
     942      } else {
     943        nextbit = count_leading_zeros(bits);
     944        if ((diff = (nextbit - bitidx)) != 0) {
     945          memo_dnode += diff;
     946          bitidx = nextbit;
     947          p += (diff+diff);
     948        }
     949        x1 = p[0];
     950        x2 = p[1];
     951        tag_x1 = fulltag_of(x1);
     952        bits &= ~(BIT0_MASK >> bitidx);
     953        header_p = (nodeheader_tag_p(tag_x1));
     954
     955        if (header_p &&
     956            (header_subtag(x1) == subtag_hash_vector)) {
     957          hashp = (hash_table_vector_header *) p;
     958          if (hashp->flags & nhash_track_keys_mask) {
     959            hash_dnode_limit = memo_dnode + ((header_element_count(x1)+2)>>1);
     960          } else {
     961            hashp = NULL;
     962          }
     963        }
     964
     965
     966        if (! header_p) {
     967          new = node_forwarding_address(x1);
     968          if (new != x1) {
     969            *p = new;
     970          }
     971        }
     972        p++;
     973
     974        new = node_forwarding_address(x2);
     975        if (new != x2) {
    968976          *p = new;
    969         }
    970       }
    971       p++;
    972 
    973       new = node_forwarding_address(x2);
    974       if (new != x2) {
    975         *p = new;
    976         if (memo_dnode < hash_dnode_limit) {
    977           /* If this code is reached, 'hashp' is non-NULL and pointing
    978              at the header of a hash_table_vector, and 'memo_dnode' identifies
    979              a pair of words inside the hash_table_vector.  It may be
    980              hard for program analysis tools to recognize that, but I
    981              believe that warnings about 'hashp' being NULL here can
    982              be safely ignored. */
    983           hashp->flags |= nhash_key_moved_mask;
    984           hash_dnode_limit = 0;
    985           hashp = NULL;
    986         }
    987       }
    988       p++;
    989       memo_dnode++;
    990       bitidx++;
    991 
     977          if (memo_dnode < hash_dnode_limit) {
     978            /* If this code is reached, 'hashp' is non-NULL and pointing
     979               at the header of a hash_table_vector, and 'memo_dnode' identifies
     980               a pair of words inside the hash_table_vector.  It may be
     981               hard for program analysis tools to recognize that, but I
     982               believe that warnings about 'hashp' being NULL here can
     983               be safely ignored. */
     984            hashp->flags |= nhash_key_moved_mask;
     985            hash_dnode_limit = 0;
     986            hashp = NULL;
     987          }
     988        }
     989        p++;
     990        memo_dnode++;
     991        bitidx++;
     992
     993      }
    992994    }
    993995  }
     
    10851087#endif
    10861088
     1089
     1090Boolean
     1091mark_static_ref(LispObj n, BytePtr dynamic_start, natural ndynamic_dnodes)
     1092{
     1093  int tag_n = fulltag_of(n);
     1094  natural dyn_dnode;
     1095
     1096  if (nodeheader_tag_p(tag_n)) {
     1097    return (header_subtag(n) == subtag_hash_vector);
     1098  }
     1099 
     1100  if (is_node_fulltag (tag_n)) {
     1101    dyn_dnode = area_dnode(n, dynamic_start);
     1102    if (dyn_dnode < ndynamic_dnodes) {
     1103      mark_root(n);             /* May or may not mark it */
     1104      return true;              /* but return true 'cause it's a dynamic node */
     1105    }
     1106  }
     1107  return false;                 /* Not a heap pointer or not dynamic */
     1108}
     1109
     1110void
     1111mark_managed_static_refs(area *a, BytePtr low_dynamic_address, natural ndynamic_dnodes)
     1112{
     1113  bitvector refbits = a->refbits;
     1114  LispObj *p = (LispObj *) a->low, x1, x2;
     1115  natural inbits, outbits, bits, bitidx, *bitsp, nextbit, diff, memo_dnode = 0,
     1116    num_memo_dnodes = a->ndnodes;
     1117  Boolean keep_x1, keep_x2;
     1118
     1119  if (num_memo_dnodes) {
     1120    if (GCDebug) {
     1121      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
     1122    }
     1123
     1124 
     1125    set_bitidx_vars(refbits, 0, bitsp, bits, bitidx);
     1126    inbits = outbits = bits;
     1127    while (memo_dnode < num_memo_dnodes) {
     1128      if (bits == 0) {
     1129        int remain = nbits_in_word - bitidx;
     1130        memo_dnode += remain;
     1131        p += (remain+remain);
     1132        if (outbits != inbits) {
     1133          *bitsp = outbits;
     1134        }
     1135        bits = *++bitsp;
     1136        inbits = outbits = bits;
     1137        bitidx = 0;
     1138      } else {
     1139        nextbit = count_leading_zeros(bits);
     1140        if ((diff = (nextbit - bitidx)) != 0) {
     1141          memo_dnode += diff;
     1142          bitidx = nextbit;
     1143          p += (diff+diff);
     1144        }
     1145        x1 = *p++;
     1146        x2 = *p++;
     1147        bits &= ~(BIT0_MASK >> bitidx);
     1148        keep_x1 = mark_static_ref(x1, low_dynamic_address, ndynamic_dnodes);
     1149        keep_x2 = mark_static_ref(x2, low_dynamic_address, ndynamic_dnodes);
     1150        if ((keep_x1 == false) &&
     1151            (keep_x2 == false)) {
     1152          outbits &= ~(BIT0_MASK >> bitidx);
     1153        }
     1154        memo_dnode++;
     1155        bitidx++;
     1156      }
     1157    }
     1158    if (GCDebug) {
     1159      p = (LispObj *) a->low;
     1160      check_refmap_consistency(p, p+(num_memo_dnodes << 1), refbits);
     1161    }
     1162  }
     1163}
    10871164
    10881165void
     
    12611338    }
    12621339
     1340    mark_managed_static_refs(managed_static_area,low_markable_address,area_dnode(a->active,low_markable_address));
     1341   
    12631342    other_tcr = tcr;
    12641343    do {
     
    13931472    }
    13941473 
     1474    forward_memoized_area(managed_static_area,area_dnode(managed_static_area->active,managed_static_area->low));
    13951475    a->active = (BytePtr) ptr_from_lispobj(compact_dynamic_heap());
    13961476    if (to) {
  • branches/purify/source/lisp-kernel/gc.h

    r12378 r13042  
    240240extern xmacptr_dispose_fn xmacptr_dispose_functions[];
    241241
     242extern bitvector global_mark_ref_bits, dynamic_mark_ref_bits;
     243
     244
    242245#endif                          /* __GC_H__ */
  • branches/purify/source/lisp-kernel/image.c

    r12890 r13042  
    229229    a->active = a->low+mem_size;
    230230    if (mem_size) {
     231      natural
     232        refbits_size = align_to_power_of_2((((mem_size>>dnode_shift)+7)>>3),
     233                                           log2_page_size);
    231234      if (!MapFile(a->low,
    232235                   pos,
     
    236239        return;
    237240      }
    238     }
    239     /* Need to save/restore persistent refbits. */
     241      /* Need to save/restore persistent refbits. */
     242      if (!MapFile(global_mark_ref_bits,
     243                   align_to_power_of_2(pos+mem_size,log2_page_size),
     244                   refbits_size,
     245                   MEMPROTECT_RW,
     246                   fd)) {
     247        return;
     248      }
     249      advance += refbits_size;
     250    }
    240251    sect->area = a;
     252    a->ndnodes = area_dnode(a->active, a->low);
    241253    managed_static_area = a;
     254    lisp_global(REF_BASE) = (LispObj) a->low;
    242255    break;
    243256
     
    252265    addr = (void *) lisp_global(HEAP_START);
    253266    a = new_area(addr-align_to_power_of_2(mem_size,log2_page_size), addr, AREA_STATIC_CONS);
     267    if (mem_size) {     
     268      if (!MapFile(a->low,
     269                   pos,
     270                   align_to_power_of_2(mem_size,log2_page_size),
     271                   MEMPROTECT_RWX,
     272                   fd)) {
     273        return;
     274      }
     275    }
     276    a->ndnodes = area_dnode(a->active, a->low);
    254277    sect->area = a;
    255278    static_cons_area = a;
     
    533556        return errno;
    534557    }
     558    if (n &&  ((sections[i].code) == AREA_MANAGED_STATIC)) {
     559      natural ndnodes = area_dnode(a->active, a->low);
     560      natural nrefbytes = align_to_power_of_2((ndnodes+7)>>3,log2_page_size);
     561
     562      seek_to_next_page(fd);
     563      if (writebuf(fd,(char*)a->refbits,nrefbytes)) {
     564        return errno;
     565      }
     566    }
    535567  }
    536568
  • branches/purify/source/lisp-kernel/lisp_globals.h

    r12128 r13042  
    6161#define OLDEST_EPHEMERAL (-39)  /* doubleword address of oldest ephemeral object or 0 */
    6262#define TENURED_AREA (-40)      /* the tenured area */
    63 #define ERRNO (-41)             /* address of errno */
     63#define REF_BASE (-41)          /* start of oldest pointer-bearing area */
    6464#define ARGV (-42)              /* pointer to &argv[0] */
    6565#define HOST_PLATFORM (-43)     /* for platform-specific initialization */
  • branches/purify/source/lisp-kernel/memory.c

    r12807 r13042  
    773773   
    774774  a->markbits = new_markbits;
    775   lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(curfree, lisp_global(HEAP_START));
     775  lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(curfree, lisp_global(REF_BASE));
    776776}
    777777
     
    808808      /* Everything's in the dynamic area */
    809809      lisp_global(OLDEST_EPHEMERAL) = 0;
    810       lisp_global(OLDSPACE_DNODE_COUNT) = 0;
     810      lisp_global(OLDSPACE_DNODE_COUNT) = area_dnode(managed_static_area->active,managed_static_area->low);
    811811
    812812    }
  • branches/purify/source/lisp-kernel/pmcl-kernel.c

    r12894 r13042  
    137137
    138138LispObj lisp_nil = (LispObj) 0;
    139 bitvector global_mark_ref_bits = NULL;
     139bitvector global_mark_ref_bits = NULL, dynamic_mark_ref_bits = NULL;
    140140
    141141
     
    511511
    512512area *
    513 extend_readonly_area(unsigned more)
     513extend_readonly_area(natural more)
    514514{
    515515  area *a;
     
    607607  reserved->pred = reserved->succ = reserved;
    608608  all_areas = reserved;
    609   reserved->markbits = global_mark_ref_bits;
    610609  return reserved;
    611610}
     
    632631
    633632BytePtr reloctab_limit = NULL, markbits_limit = NULL;
     633BytePtr low_relocatable_address = NULL, high_relocatable_address = NULL,
     634  low_markable_address = NULL, high_markable_address = NULL;
     635
     636void
     637map_initial_reloctab(BytePtr low, BytePtr high) 
     638{
     639  natural ndnodes, reloctab_size, n;
     640
     641  low_relocatable_address = low; /* will never change */
     642  high_relocatable_address = high;
     643  ndnodes = area_dnode(high,low);
     644  reloctab_size = (sizeof(LispObj)*(((ndnodes+((1<<bitmap_shift)-1))>>bitmap_shift)+1));
     645 
     646  reloctab_limit = (BytePtr)align_to_power_of_2(((natural)global_reloctab)+reloctab_size,log2_page_size);
     647  CommitMemory(global_reloctab,reloctab_limit-(BytePtr)global_reloctab);
     648}
     649
     650void
     651map_initial_markbits(BytePtr low, BytePtr high)
     652{
     653  natural
     654    prefix_dnodes = area_dnode(low, pure_space_limit),
     655    ndnodes = area_dnode(high, low),
     656    prefix_size = (prefix_dnodes+7)>>3,
     657    markbits_size = (3*sizeof(LispObj))+((ndnodes+7)>>3),
     658    n;
     659  low_markable_address = low;
     660  high_markable_address = high;
     661  dynamic_mark_ref_bits = (bitvector)(((BytePtr)global_mark_ref_bits)+prefix_size);
     662  n = align_to_power_of_2(markbits_size,log2_page_size);
     663  markbits_limit = ((BytePtr)dynamic_mark_ref_bits)+n;
     664  CommitMemory(dynamic_mark_ref_bits,n);
     665}
     666   
    634667
    635668void
     
    643676  BytePtr
    644677    new_reloctab_limit = (BytePtr)align_to_power_of_2(((natural)global_reloctab)+reloctab_size,log2_page_size),
    645     new_markbits_limit = (BytePtr)align_to_power_of_2(((natural)global_mark_ref_bits)+markbits_size,log2_page_size);
     678    new_markbits_limit = (BytePtr)align_to_power_of_2(((natural)dynamic_mark_ref_bits)+markbits_size,log2_page_size);
    646679
    647680  if (new_reloctab_limit > reloctab_limit) {
     
    677710  a->active = start+initsize;
    678711  add_area_holding_area_lock(a);
    679   a->markbits = reserved_area->markbits;
    680   reserved_area->markbits = NULL;
    681712  CommitMemory(start, end-start);
    682713  a->h = start;
    683714  a->softprot = NULL;
    684715  a->hardprot = NULL;
     716  map_initial_reloctab(a->low, a->high);
     717  map_initial_markbits(a->low, a->high);
    685718  lisp_global(HEAP_START) = ptr_to_lispobj(a->low);
    686719  lisp_global(HEAP_END) = ptr_to_lispobj(a->high);
    687   markbits_limit = (BytePtr)global_mark_ref_bits;
    688   reloctab_limit = (BytePtr)global_reloctab;
    689   ensure_gc_structures_writable();
    690720  return a;
    691721 }
     
    18951925    g2_area->older = tenured_area;
    18961926    tenured_area->younger = g2_area;
    1897     tenured_area->refbits = a->markbits;
     1927    tenured_area->refbits = dynamic_mark_ref_bits;
     1928    managed_static_area->refbits = global_mark_ref_bits;
     1929    a->markbits = dynamic_mark_ref_bits;
    18981930    tenured_area->static_dnodes = a->static_dnodes;
    18991931    a->static_dnodes = 0;
     
    19011933    a->static_used = 0;
    19021934    lisp_global(TENURED_AREA) = ptr_to_lispobj(tenured_area);
    1903     lisp_global(REFBITS) = ptr_to_lispobj(tenured_area->refbits);
     1935    lisp_global(REFBITS) = ptr_to_lispobj(global_mark_ref_bits);
    19041936    g2_area->threshold = default_g2_threshold;
    19051937    g1_area->threshold = default_g1_threshold;
  • branches/purify/source/lisp-kernel/ppc-constants.s

    r12657 r13042  
    194194         _node(host_platform)           /* for runtime platform-specific stuff */
    195195         _node(argv)                    /* address of argv[0] */
    196          _node(errno)                   /* ADDRESS of errno */
     196         _node(ref_base)                        /* start of oldest pointer-bearing area */
    197197         _node(tenured_area)            /* the tenured_area */
    198198         _node(oldest_ephemeral)        /* dword address of oldest ephemeral object or 0 */
     
    209209         _node(kernel_path)             /* real executable name */
    210210         _node(objc2_begin_catch)       /* objc_begin_catch */
    211          _node(BAD_current_vs)          /* current value-stack area  */
     211         _node(stack_size)              /* from command-line */
    212212         _node(statically_linked)       /* non-zero if -static */
    213213         _node(heap_end)                /* end of lisp heap */
  • branches/purify/source/lisp-kernel/x86-constants.s

    r12656 r13042  
    7676         _node(host_platform)           /* for runtime platform-specific stuff   */
    7777         _node(argv)                    /* address of argv[0]   */
    78          _node(errno)                   /* ADDRESS of errno  */
     78         _node(ref_base)                /* start of oldest pointer-bearing area */
    7979         _node(tenured_area)            /* the tenured_area   */
    8080         _node(oldest_ephemeral)        /* dword address of oldest ephemeral object or 0   */
     
    9191         _node(kernel_path)             /* real executable name */
    9292         _node(objc2_begin_catch)       /* objc_begin_catch   */
    93          _node(BAD_current_vs)          /* current value-stack area  */
     93         _node(stack_size)              /* from the command line */
    9494         _node(statically_linked)       /* non-zero if -static   */
    9595         _node(heap_end)                /* end of lisp heap   */
  • branches/purify/source/lisp-kernel/x86-exceptions.c

    r12837 r13042  
    262262      }
    263263      if (selector & GC_TRAP_FUNCTION_PURIFY) {
    264         purify_from_xp(xp, 0L);
     264        /* There should be exactly one xp in the world (this one) if we're saving
     265           an image, and we'll never return to it.  If we copy functions,
     266           we'll have difficulty updating the PC in that xp and a subsequent
     267           GC will be confused by that, so zero it here */       
     268        if (selector & GC_TRAP_FUNCTION_SAVE_APPLICATION) {
     269          xpPC(xp)=(LispObj)0;
     270        }
     271        purify_from_xp(xp, selector & GC_TRAP_FUNCTION_SAVE_APPLICATION);
    265272        gc_from_xp(xp, 0L);
    266273      }
     
    26032610    }
    26042611    if (need_check_memo) {
    2605       natural  bitnumber = area_dnode(ea, lisp_global(HEAP_START));
     2612      natural  bitnumber = area_dnode(ea, lisp_global(REF_BASE));
    26062613      if ((bitnumber < lisp_global(OLDSPACE_DNODE_COUNT)) &&
    26072614          ((LispObj)ea < val)) {
    26082615        atomic_set_bit(refbits, bitnumber);
    26092616        if (need_memoize_root) {
    2610           bitnumber = area_dnode(root, lisp_global(HEAP_START));
     2617          bitnumber = area_dnode(root, lisp_global(REF_BASE));
    26112618          atomic_set_bit(refbits, bitnumber);
    26122619        }
  • branches/purify/source/lisp-kernel/x86-gc.c

    r12815 r13042  
    598598  return false;                 /* Not a heap pointer or not ephemeral */
    599599}
     600
     601
     602
     603
     604
    600605 
    601606
     
    13011306  }
    13021307}
     1308
    13031309
    13041310void
     
    21042110
    21052111
    2106 
    2107 
    2108 
    2109      
     2112#define PURIFY_IVECTORS (1<<0)
     2113#define PURIFY_FUNCTIONS (1<<1)
     2114#define PURIFY_ALL (-1)
     2115#define PURIFY_NOTHING (0)      /* update forwarding pointers, don't copy */
     2116
     2117
     2118
     2119Boolean
     2120immutable_function_p(LispObj thing)
     2121{
     2122  LispObj header = header_of(thing), lfbits;
     2123  if (header_subtag(header) == subtag_function) {
     2124    lfbits = deref(thing,header_element_count(header));
     2125    if (((lfbits & (lfbits_cm_mask | lfbits_method_mask)) !=
     2126         lfbits_cm_mask) &&
     2127        ((lfbits & (lfbits_gfn_mask | lfbits_method_mask)) !=
     2128         lfbits_gfn_mask)) {
     2129      return true;
     2130    }
     2131  }
     2132  return false;
     2133}
     2134
    21102135   
    21112136/*
     
    21142139
    21152140natural
    2116 unboxed_bytes_in_range(LispObj *start, LispObj *end)
     2141unboxed_bytes_in_range(LispObj *start, LispObj *end, Boolean include_functions)
    21172142{
    21182143  natural total=0, elements, tag, subtag, bytes;
     
    21272152      elements = header_element_count(header);
    21282153      if (nodeheader_tag_p(tag)) {
     2154        if (include_functions && immutable_function_p((LispObj)start)) {
     2155          total += (((elements+2)&~1)<<node_shift);
     2156        }
    21292157        start += ((elements+2) & ~1);
    21302158      } else {
     
    21762204
    21772205
    2178 /*
    2179   This assumes that it's getting called with a simple-{base,general}-string
    2180   or code vector as an argument and that there's room for the object in the
    2181   destination area.
    2182 */
    2183 
     2206void
     2207ensure_writable_space(area *target, natural need)
     2208{
     2209  BytePtr
     2210    oldlimit = (BytePtr)align_to_power_of_2(target->active,log2_page_size),
     2211    newlimit = (BytePtr)align_to_power_of_2(target->active+need,log2_page_size);
     2212  if (newlimit > oldlimit) {
     2213    UnProtectMemory(oldlimit,newlimit-oldlimit);
     2214  }
     2215}
    21842216
    21852217LispObj
     
    21952227    start = (natural)old,
    21962228    physbytes;
    2197 
    2198   physbytes = ((natural)(skip_over_ivector(start,header))) - start;
    2199 
     2229  int
     2230    header_tag = fulltag_of(header);
     2231
     2232  if (immheader_tag_p(header_tag)) {
     2233    physbytes = ((natural)(skip_over_ivector(start,header))) - start;
     2234  } else if (nodeheader_tag_p(header_tag)) {
     2235    physbytes = ((header_element_count(header)+2)&~1) << node_shift;
     2236  } else {
     2237    physbytes = dnode_size;
     2238  }
     2239 
     2240  ensure_writable_space(dest, physbytes);
    22002241  dest->active += physbytes;
    22012242
     
    22282269
    22292270Boolean
    2230 copy_ivector_reference(LispObj *ref, BytePtr low, BytePtr high, area *dest)
     2271copy_reference(LispObj *ref, BytePtr low, BytePtr high, area *dest, int what)
    22312272{
    22322273  LispObj obj = *ref, header, new;
     
    22342275  Boolean changed = false;
    22352276
    2236   if ((tag == fulltag_misc) &&
    2237       (((BytePtr)ptr_from_lispobj(obj)) > low) &&
    2238       (((BytePtr)ptr_from_lispobj(obj)) < high)) {
    2239     header = deref(obj, 0);
    2240     if (header == forward_marker) { /* already copied */
    2241       *ref = (untag(deref(obj,1)) + tag);
    2242       changed = true;
    2243     } else {
    2244       header_tag = fulltag_of(header);
    2245       if (immheader_tag_p(header_tag)) {
    2246         if (header_subtag(header) != subtag_macptr) {
     2277  if (
     2278#ifdef X8664
     2279      (tag != fulltag_tra_0) && (tag != fulltag_tra_1)
     2280#endif
     2281#ifdef X8632
     2282      tag != fulltag_tra
     2283#endif
     2284      ) {
     2285    if (is_node_fulltag(tag) &&
     2286        (((BytePtr)ptr_from_lispobj(obj)) > low) &&
     2287        (((BytePtr)ptr_from_lispobj(obj)) < high)) {
     2288      header = deref(obj, 0);
     2289      if (header == forward_marker) { /* already copied */
     2290        *ref = (untag(deref(obj,1)) + tag);
     2291        changed = true;
     2292      } else {
     2293        header_tag = fulltag_of(header);
     2294        if ((what == PURIFY_ALL) ||
     2295            ((what & PURIFY_IVECTORS) &&
     2296             immheader_tag_p(header_tag) &&
     2297             header_subtag(header) != subtag_macptr) ||
     2298            ((what & PURIFY_FUNCTIONS) &&
     2299             immutable_function_p(obj))) {
    22472300          new = purify_object(obj, dest);
    22482301          *ref = new;
     
    22572310
    22582311void
    2259 purify_gcable_ptrs(BytePtr low, BytePtr high, area *to)
     2312purify_gcable_ptrs(BytePtr low, BytePtr high, area *to, int what)
    22602313{
    22612314  LispObj *prev = &(lisp_global(GCABLE_POINTERS)), next;
    22622315
    22632316  while ((*prev) != (LispObj)NULL) {
    2264     copy_ivector_reference(prev, low, high, to);
     2317    copy_reference(prev, low, high, to, what);
    22652318    next = *prev;
    22662319    prev = &(((xmacptr *)ptr_from_lispobj(untag(next)))->link);
     
    22692322
    22702323void
    2271 purify_headerless_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to)
     2324purify_headerless_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to, int what)
    22722325{
    22732326  while (start < end) {
    2274     copy_ivector_reference(start, low, high, to);
     2327    copy_reference(start, low, high, to, what);
    22752328    start++;
    22762329  }
     
    22782331   
    22792332void
    2280 purify_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to)
     2333purify_range(LispObj *start, LispObj *end, BytePtr low, BytePtr high, area *to, int what)
    22812334{
    22822335  LispObj header;
     
    23052358          nwords -= skip;
    23062359          while(skip--) {
    2307             copy_ivector_reference(start, low, high, to);
     2360            copy_reference(start, low, high, to, what);
    23082361            start++;
    23092362          }
     
    23142367          nwords >>= 1;
    23152368          while(nwords--) {
    2316             if (copy_ivector_reference(start, low, high, to) && hashp) {
     2369            if (copy_reference(start, low, high, to, what) && hashp) {
    23172370              hashp->flags |= nhash_key_moved_mask;
    23182371              hashp = NULL;
    23192372            }
    23202373            start++;
    2321             copy_ivector_reference(start, low, high, to);
     2374            copy_reference(start, low, high, to, what);
    23222375            start++;
    23232376          }
     
    23392392          start++;
    23402393          while(nwords--) {
    2341             copy_ivector_reference(start, low, high, to);
     2394            copy_reference(start, low, high, to, what);
    23422395            start++;
    23432396          }
     
    23452398      } else {
    23462399        /* Not a header, just a cons cell */
    2347         copy_ivector_reference(start, low, high, to);
     2400        copy_reference(start, low, high, to, what);
    23482401        start++;
    2349         copy_ivector_reference(start, low, high, to);
     2402        copy_reference(start, low, high, to, what);
    23502403        start++;
    23512404      }
     
    23562409/* Purify references from tstack areas */
    23572410void
    2358 purify_tstack_area(area *a, BytePtr low, BytePtr high, area *to)
     2411purify_tstack_area(area *a, BytePtr low, BytePtr high, area *to, int what)
    23592412{
    23602413  LispObj
     
    23702423    next = (LispObj *) ptr_from_lispobj(*current);
    23712424    end = ((next >= start) && (next < limit)) ? next : limit;
    2372     purify_range(current+2, end, low, high, to);
     2425    purify_range(current+2, end, low, high, to, what);
    23732426  }
    23742427}
     
    23762429/* Purify a vstack area */
    23772430void
    2378 purify_vstack_area(area *a, BytePtr low, BytePtr high, area *to)
     2431purify_vstack_area(area *a, BytePtr low, BytePtr high, area *to, int what)
    23792432{
    23802433  LispObj
     
    23822435    *q = (LispObj *) a->high;
    23832436 
    2384   purify_headerless_range(p, q, low, high, to);
    2385 }
    2386 
    2387 
    2388 void
    2389 purify_xp(ExceptionInformation *xp, BytePtr low, BytePtr high, area *to)
     2437  purify_headerless_range(p, q, low, high, to, what);
     2438}
     2439
     2440
     2441void
     2442purify_xp(ExceptionInformation *xp, BytePtr low, BytePtr high, area *to, int what)
    23902443{
    23912444  natural *regs = (natural *) xpGPRvector(xp);
     
    23932446
    23942447#ifdef X8664
    2395   copy_ivector_reference(&(regs[Iarg_z]), low, high, to);
    2396   copy_ivector_reference(&(regs[Iarg_y]), low, high, to);
    2397   copy_ivector_reference(&(regs[Iarg_x]), low, high, to);
    2398   copy_ivector_reference(&(regs[Isave3]), low, high, to);
    2399   copy_ivector_reference(&(regs[Isave2]), low, high, to);
    2400   copy_ivector_reference(&(regs[Isave1]), low, high, to);
    2401   copy_ivector_reference(&(regs[Isave0]), low, high, to);
    2402   copy_ivector_reference(&(regs[Ifn]), low, high, to);
    2403   copy_ivector_reference(&(regs[Itemp0]), low, high, to);
    2404   copy_ivector_reference(&(regs[Itemp1]), low, high, to);
    2405   copy_ivector_reference(&(regs[Itemp2]), low, high, to);
     2448  copy_reference(&(regs[Iarg_z]), low, high, to, what);
     2449  copy_reference(&(regs[Iarg_y]), low, high, to, what);
     2450  copy_reference(&(regs[Iarg_x]), low, high, to, what);
     2451  copy_reference(&(regs[Isave3]), low, high, to, what);
     2452  copy_reference(&(regs[Isave2]), low, high, to, what);
     2453  copy_reference(&(regs[Isave1]), low, high, to, what);
     2454  copy_reference(&(regs[Isave0]), low, high, to, what);
     2455  copy_reference(&(regs[Ifn]), low, high, to, what);
     2456  copy_reference(&(regs[Itemp0]), low, high, to, what);
     2457  copy_reference(&(regs[Itemp1]), low, high, to, what);
     2458  copy_reference(&(regs[Itemp2]), low, high, to, what);
    24062459#if 0
    2407   purify_locref(&(regs[Iip]), low, high, to);
     2460  purify_locref(&(regs[Iip]), low, high, to, what);
    24082461#endif
    24092462#else
     
    24122465
    24132466void
    2414 purify_tcr_tlb(TCR *tcr, BytePtr low, BytePtr high, area *to)
     2467purify_tcr_tlb(TCR *tcr, BytePtr low, BytePtr high, area *to, int what)
    24152468{
    24162469  natural n = tcr->tlb_limit;
    24172470  LispObj *start = tcr->tlb_pointer, *end = (LispObj *) ((BytePtr)start+n);
    24182471
    2419   purify_range(start, end, low, high, to);
    2420 }
    2421 
    2422 void
    2423 purify_tcr_xframes(TCR *tcr, BytePtr low, BytePtr high, area *to)
     2472  purify_range(start, end, low, high, to, what);
     2473}
     2474
     2475void
     2476purify_tcr_xframes(TCR *tcr, BytePtr low, BytePtr high, area *to, int what)
    24242477{
    24252478  xframe_list *xframes;
     
    24282481  xp = tcr->gc_context;
    24292482  if (xp) {
    2430     purify_xp(xp, low, high, to);
     2483    purify_xp(xp, low, high, to, what);
    24312484  }
    24322485
    24332486  for (xframes = tcr->xframe; xframes; xframes = xframes->prev) {
    2434     purify_xp(xframes->curr, low, high, to);
    2435   }
    2436 }
    2437 
    2438 
    2439 void
    2440 purify_areas(BytePtr low, BytePtr high, area *target)
     2487    purify_xp(xframes->curr, low, high, to, what);
     2488  }
     2489}
     2490
     2491
     2492void
     2493purify_areas(BytePtr low, BytePtr high, area *target, int what)
    24412494{
    24422495  area *next_area;
     
    24462499    switch (code) {
    24472500    case AREA_TSTACK:
    2448       purify_tstack_area(next_area, low, high, target);
     2501      purify_tstack_area(next_area, low, high, target, what);
    24492502      break;
    24502503     
    24512504    case AREA_VSTACK:
    2452       purify_vstack_area(next_area, low, high, target);
     2505      purify_vstack_area(next_area, low, high, target, what);
    24532506      break;
    24542507     
     
    24582511    case AREA_STATIC:
    24592512    case AREA_DYNAMIC:
    2460       purify_range((LispObj *) next_area->low, (LispObj *) next_area->active, low, high, target);
     2513    case AREA_MANAGED_STATIC:
     2514      purify_range((LispObj *) next_area->low, (LispObj *) next_area->active, low, high, target, what);
    24612515      break;
    24622516     
     
    24672521}
    24682522
     2523void
     2524update_managed_refs(area *a, BytePtr low_dynamic_address, natural ndynamic_dnodes)
     2525{
     2526  LispObj
     2527    *start = (LispObj *)a->low,
     2528    *end = (LispObj *)a->active,
     2529    x1,
     2530    *base = start, *prev = start;
     2531  int tag;
     2532  bitvector refbits = a->refbits;
     2533  natural ref_dnode, node_dnode;
     2534  Boolean intergen_ref;
     2535
     2536  while (start < end) {
     2537    x1 = *start;
     2538    prev = start;
     2539    tag = fulltag_of(x1);
     2540    if (immheader_tag_p(tag)) {
     2541      start = skip_over_ivector(ptr_to_lispobj(start), x1);
     2542    } else {
     2543      if (header_subtag(x1) == subtag_function) {
     2544#ifdef X8632
     2545        int skip = (unsigned short)deref(start,1);
     2546        /* XXX bootstrapping */
     2547        if (skip & 0x8000)
     2548          skip = header_element_count(x1) - (skip & 0x7fff);
     2549#else
     2550        int skip = (int) deref(start,1);
     2551#endif
     2552        start += ((1+skip)&~1);
     2553        x1 = *start;
     2554        tag = fulltag_of(x1);
     2555      }
     2556      intergen_ref = false;
     2557      if (is_node_fulltag(tag)) {       
     2558        node_dnode = area_dnode(x1, low_dynamic_address);
     2559        if (node_dnode < ndynamic_dnodes) {
     2560          intergen_ref = true;
     2561        }
     2562      }
     2563      if (intergen_ref == false) {       
     2564        x1 = start[1];
     2565        tag = fulltag_of(x1);
     2566        if (is_node_fulltag(tag)) {       
     2567          node_dnode = area_dnode(x1, low_dynamic_address);
     2568          if (node_dnode < ndynamic_dnodes) {
     2569            intergen_ref = true;
     2570          }
     2571        }
     2572      }
     2573      if (intergen_ref) {
     2574        ref_dnode = area_dnode(start, base);
     2575        set_bit(refbits, ref_dnode);
     2576      }
     2577      start += 2;
     2578    }
     2579  }
     2580  if (start > end) {
     2581    Bug(NULL, "Overran end of range!");
     2582  }
     2583}
     2584
    24692585/*
    24702586  So far, this is mostly for save_application's benefit.
     
    24782594purify(TCR *tcr, signed_natural param)
    24792595{
    2480   extern area *extend_readonly_area(unsigned);
     2596  extern area *extend_readonly_area(natural);
    24812597  area
    24822598    *a = active_dynamic_area,
    2483     *new_pure_area;
     2599    *pure_area;
    24842600
    24852601  TCR  *other_tcr;
     
    24882604    low = (a->low + (static_dnodes_for_area(a) << dnode_shift)),
    24892605    high = a->active;
    2490 
    2491 
    2492   max_pure_size = unboxed_bytes_in_range((LispObj *) low, (LispObj *) high);
    2493   new_pure_area = extend_readonly_area(max_pure_size);
    2494   if (new_pure_area) {
    2495     new_pure_start = new_pure_area->active;
     2606  Boolean purify_functions = (param != 0);
     2607  int flags = PURIFY_IVECTORS | (purify_functions ? PURIFY_FUNCTIONS : 0);
     2608
     2609  max_pure_size = unboxed_bytes_in_range((LispObj *) low, (LispObj *) high, purify_functions);
     2610  pure_area = extend_readonly_area(max_pure_size);
     2611  if (pure_area) {
     2612    new_pure_start = pure_area->active;
    24962613    lisp_global(IN_GC) = (1<<fixnumshift);
    24972614
    24982615    /*
    2499 
    2500        
    2501       Make the new_pure_area executable, just in case.
    2502 
    25032616      Caller will typically GC again (and that should recover quite a bit of
    25042617      the dynamic heap.)
     
    25072620
    25082621   
    2509     purify_areas(low, high, new_pure_area);
     2622    purify_areas(low, high, pure_area, flags);
    25102623   
    25112624    other_tcr = tcr;
    25122625    do {
    2513       purify_tcr_xframes(other_tcr, low, high, new_pure_area);
    2514       purify_tcr_tlb(other_tcr, low, high, new_pure_area);
     2626      purify_tcr_xframes(other_tcr, low, high, pure_area, flags);
     2627      purify_tcr_tlb(other_tcr, low, high, pure_area, flags);
    25152628      other_tcr = other_tcr->next;
    25162629    } while (other_tcr != tcr);
    25172630
    2518     purify_gcable_ptrs(low, high, new_pure_area);
    2519     {
    2520       natural puresize = (unsigned) (new_pure_area->active-new_pure_start);
    2521       if (puresize != 0) {
    2522         xMakeDataExecutable(new_pure_start, puresize);
    2523  
    2524       }
    2525     }
    2526     ProtectMemory(new_pure_area->low,
    2527                   align_to_power_of_2(new_pure_area->active-new_pure_area->low,
     2631    purify_gcable_ptrs(low, high, pure_area, flags);
     2632    if (purify_functions) {
     2633      /* We're likely to copy a lot of symbols to the managed static
     2634         area.  Lots of symbols will have incidental references to
     2635         a relatively small number of things that happen to initialy
     2636         be in dynamic space: the UNDEFINED-FUNCTION object, packages,
     2637         etc.  Doing a shallow copy of those things to the managed-static
     2638         area will reduce the number of static->dynamic references. */
     2639      LispObj package_list;
     2640
     2641      copy_reference(&nrs_UDF.vcell,low,high,managed_static_area,PURIFY_ALL);
     2642      for (package_list = nrs_ALL_PACKAGES.vcell;
     2643           package_list != lisp_nil;
     2644           package_list = deref(package_list,0)) {
     2645        copy_reference(&(deref(package_list,1)),low,high,managed_static_area,PURIFY_ALL);
     2646      }
     2647
     2648       
     2649
     2650      /* Do a shallow copy of the constants of all purified functions
     2651         from the dynamic area to the managed static area */
     2652      purify_range((LispObj*)(pure_area->low),
     2653                   (LispObj*)(pure_area->active),
     2654                   low,
     2655                   high,
     2656                   managed_static_area,
     2657                   PURIFY_ALL);
     2658      /* Go back through all areas, resolving forwarding pointers
     2659         (but without copying anything.) */
     2660      purify_areas(low, high, NULL, PURIFY_NOTHING);
     2661      other_tcr = tcr;
     2662      do {
     2663        purify_tcr_xframes(other_tcr, low, high, NULL, PURIFY_NOTHING);
     2664        purify_tcr_tlb(other_tcr, low, high, NULL, PURIFY_NOTHING);
     2665        other_tcr = other_tcr->next;
     2666      } while (other_tcr != tcr);
     2667     
     2668      purify_gcable_ptrs(low, high, NULL, PURIFY_NOTHING);
     2669
     2670      /* Update refbits for managed static area */
     2671      {
     2672        natural
     2673          managed_dnodes = area_dnode(managed_static_area->active,
     2674                                      managed_static_area->low),
     2675          refbytes = align_to_power_of_2((managed_dnodes+7)>>3,log2_page_size);
     2676       
     2677        managed_static_area->ndnodes = managed_dnodes;
     2678        CommitMemory(managed_static_area->refbits, refbytes); /* zeros them */
     2679        update_managed_refs(managed_static_area, low_markable_address, area_dnode(a->active,low_markable_address));
     2680      }
     2681    }
     2682    ProtectMemory(pure_area->low,
     2683                  align_to_power_of_2(pure_area->active-pure_area->low,
    25282684                                      log2_page_size));
    25292685    lisp_global(IN_GC) = 0;
  • branches/purify/source/lisp-kernel/x86-spentry64.s

    r12601 r13042  
    176817680:      __(repret)
    176917691:      __(movq %arg_y,%imm0)
    1770         __(subq lisp_global(heap_start),%imm0)
     1770        __(subq lisp_global(ref_base),%imm0)
    17711771        __(shrq $dnode_shift,%imm0)
    17721772        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
     
    178717870:      __(repret)
    178817881:      __(movq %arg_y,%imm0)
    1789         __(subq lisp_global(heap_start),%imm0)
     1789        __(subq lisp_global(ref_base),%imm0)
    17901790        __(shrq $dnode_shift,%imm0)
    17911791        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
     
    180918090:      __(repret)
    181018101:      __(lea misc_data_offset(%arg_x,%arg_y),%imm0)
    1811         __(subq lisp_global(heap_start),%imm0)
     1811        __(subq lisp_global(ref_base),%imm0)
    18121812        __(shrq $dnode_shift,%imm0)
    18131813        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
     
    183318330:      __(repret)
    183418341:      __(lea misc_data_offset(%arg_x,%arg_y),%imm0)
    1835         __(subq lisp_global(heap_start),%imm0)
     1835        __(subq lisp_global(ref_base),%imm0)
    18361836        __(shrq $dnode_shift,%imm0)
    18371837        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
     
    18431843        /* Now memoize the address of the hash vector   */
    18441844        __(movq %arg_x,%imm0)
    1845         __(subq lisp_global(heap_start),%imm0)
     1845        __(subq lisp_global(ref_base),%imm0)
    18461846        __(shrq $dnode_shift,%imm0)
    18471847        __(xorb $63,%imm0_b)
     
    18731873        __(jne 0b)
    18741874        __(lea (%arg_x,%imm1),%imm0)
    1875         __(subq lisp_global(heap_start),%imm0)
     1875        __(subq lisp_global(ref_base),%imm0)
    18761876        __(shrq $dnode_shift,%imm0)
    18771877        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
     
    19051905        __(jne 0b)
    19061906        __(lea (%arg_x,%imm1),%imm0)
    1907         __(subq lisp_global(heap_start),%imm0)
     1907        __(subq lisp_global(ref_base),%imm0)
    19081908        __(shrq $dnode_shift,%imm0)
    19091909        __(cmpq lisp_global(oldspace_dnode_count),%imm0)
     
    19151915        /* Now memoize the address of the hash vector   */
    19161916        __(movq %arg_x,%imm0)
    1917         __(subq lisp_global(heap_start),%imm0)
     1917        __(subq lisp_global(ref_base),%imm0)
    19181918        __(shrq $dnode_shift,%imm0)
    19191919        __(xorb $63,%imm0_b)
Note: See TracChangeset for help on using the changeset viewer.