home *** CD-ROM | disk | FTP | other *** search
- /* values.c -- Handling of Lisp data (includes garbage collection)
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- #include <string.h>
- #include <assert.h>
-
- #ifdef HAVE_UNIX
- #include <signal.h>
- #endif
-
- /* #define GC_MONITOR_STK */
-
- #define STATIC_SMALL_NUMBERS 256
-
- _PR int valuecmp(VALUE, VALUE);
- _PR void princval(VALUE, VALUE);
- _PR void printval(VALUE, VALUE);
- _PR int nil_cmp(VALUE, VALUE);
- _PR String *valstralloc(int);
- _PR String *valstrdupn(const u_char *, int);
- _PR String *valstrdup(const u_char *);
- _PR int string_cmp(VALUE, VALUE);
- _PR Number *newnumber(long);
- _PR int number_cmp(VALUE, VALUE);
- _PR int ptr_cmp(VALUE, VALUE);
- _PR void cons_free(VALUE);
- _PR int cons_cmp(VALUE, VALUE);
- _PR VALUE list_1(VALUE);
- _PR VALUE list_2(VALUE, VALUE);
- _PR VALUE list_3(VALUE, VALUE, VALUE);
- _PR VALUE list_4(VALUE, VALUE, VALUE, VALUE);
- _PR VALUE list_5(VALUE, VALUE, VALUE, VALUE, VALUE);
- _PR Vector *newvector(int);
- _PR LPos *newlpos(POS *);
- _PR LPos *newlpos2(long, long);
- _PR int lpos_cmp(VALUE, VALUE);
- _PR void lpos_prin(VALUE, VALUE);
- _PR int vector_cmp(VALUE, VALUE);
-
- _PR void markstatic(VALUE *);
- _PR void markvalue(VALUE);
-
- _PR void values_init (void);
- _PR void values_init2(void);
- _PR void values_kill (void);
-
- ValClass ValueClasses[] = {
- { string_cmp, string_princ, string_print, MKSTR("string") },
- { string_cmp, string_princ, string_print, MKSTR("string") },
- { number_cmp, lisp_prin, lisp_prin, MKSTR("number") },
- { cons_cmp, lisp_prin, lisp_prin, MKSTR("cons") },
- { vector_cmp, lisp_prin, lisp_prin, MKSTR("vector") },
- { symbol_cmp, symbol_princ, symbol_print, MKSTR("symbol") },
- { mark_cmp, mark_prin, mark_prin, MKSTR("mark") },
- { lpos_cmp, lpos_prin, lpos_prin, MKSTR("pos") },
- { ptr_cmp, keymap_prin, keymap_prin, MKSTR("keytab") },
- { ptr_cmp, keymap_prin, keymap_prin, MKSTR("keylist") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("var") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-0") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-1") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-2") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-3") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-4") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-5") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("subr-n") },
- { ptr_cmp, lisp_prin, lisp_prin, MKSTR("special-form") },
- { ptr_cmp, buffer_prin, buffer_prin, MKSTR("buffer") },
- { ptr_cmp, window_prin, window_prin, MKSTR("window") },
- { file_cmp, file_prin, file_prin, MKSTR("file") },
- #ifdef HAVE_UNIX
- { ptr_cmp, proc_prin, proc_prin, MKSTR("process") },
- #else
- { nil_cmp, lisp_prin, lisp_prin, MKSTR("process") },
- #endif
- };
-
- int
- valuecmp(VALUE v1, VALUE v2)
- {
- if(v1 && v2)
- return(VALUECMP(v1, v2));
- return(1);
- }
- void
- princval(VALUE strm, VALUE val)
- {
- if(val)
- PRINCVAL(strm, val);
- }
- void
- printval(VALUE strm, VALUE val)
- {
- if(val)
- PRINTVAL(strm, val);
- }
-
- int
- nil_cmp(VALUE val1, VALUE val2)
- {
- if(VTYPE(val1) == VTYPE(val2))
- return(0);
- return(1);
- }
-
- static STRMEM LispStrMem;
- _PR String *NullString;
- String *NullString = MKSTR("");
- String *
- valstralloc(int slen)
- {
- String *str;
- slen = STR_SIZE(slen);
- str = sm_alloc(&LispStrMem, slen);
- if(str)
- {
- str->str_Type = V_String;
- DataAfterGC += slen;
- return(str);
- }
- return(NULL);
- }
- String *
- valstrdupn(const u_char *src, int slen)
- {
- String *dst = valstralloc(slen + 1);
- if(dst)
- {
- memcpy(dst->str_Data, src, slen);
- dst->str_Data[slen] = 0;
- }
- return(dst);
- }
- String *
- valstrdup(const u_char * src)
- {
- return(valstrdupn(src, strlen(src)));
- }
- int
- string_cmp(VALUE v1, VALUE v2)
- {
- if(STRINGP(v1) && STRINGP(v2))
- return(strcmp(VSTR(v1), VSTR(v2)));
- return(1);
- }
- static void
- string_sweep(void)
- {
- int bucket;
- MEMCHUNK *mlc;
- for(bucket = 0; bucket < NUMBUCKETS; bucket++)
- {
- MEMCHUNK **freelist = &LispStrMem.sm_MemBuckets[bucket].mbu_FreeList;
- MEMBLOCK *mbl = (MEMBLOCK *)LispStrMem.sm_MemBuckets[bucket].mbu_MemBlocks.mlh_Head;
- MEMBLOCK *nxt;
- int chnksiz = MCHNK_SIZE((bucket + 1) * GRAIN);
- int numchnks = LispStrMem.sm_ChunksPerBlock[bucket];
- *freelist = NULL;
- while((nxt = (MEMBLOCK *)mbl->mbl_Node.mln_Succ))
- {
- MEMCHUNK *mc = mbl->mbl_Chunks;
- int j;
- for(j = 0; j < numchnks; j++)
- {
- if(mc->mc_BlkType != MBT_FREE)
- {
- if(mc->mc_Mem.mem[0] & GC_MARK_BIT)
- mc->mc_Mem.mem[0] = V_String;
- else
- {
- mc->mc_BlkType = MBT_FREE;
- mc->mc_Mem.nextfree = *freelist;
- *freelist = mc;
- }
- }
- mc = (MEMCHUNK *)((char *)mc + chnksiz);
- }
- mbl = nxt;
- }
- }
- mlc = LispStrMem.sm_MallocChain;
- LispStrMem.sm_MallocChain = NULL;
- while(mlc)
- {
- MEMCHUNK *nxtmlc = mlc->mc_Header.next;
- if(mlc->mc_Mem.mem[0] == V_String)
- myfree(mlc);
- else
- {
- mlc->mc_Mem.mem[0] = V_String;
- mlc->mc_Header.next = LispStrMem.sm_MallocChain;
- LispStrMem.sm_MallocChain = mlc;
- }
- mlc = nxtmlc;
- }
- }
-
- static NumberBlk *NumberBlkChain;
- static Number *NumberFreeList;
- static int AllocatedNumbers, UsedNumbers;
-
- #ifdef STATIC_SMALL_NUMBERS
- static Number SmallNumbers[STATIC_SMALL_NUMBERS];
- #endif
-
- Number *
- newnumber(long n)
- {
- Number *num;
- #ifdef STATIC_SMALL_NUMBERS
- if((n < STATIC_SMALL_NUMBERS) && (n >= 0))
- return(&SmallNumbers[n]);
- #endif
- if(!(num = NumberFreeList))
- {
- NumberBlk *nb = mymalloc(sizeof(NumberBlk));
- if(nb)
- {
- int i;
- AllocatedNumbers += NUMBERBLK_SIZE;
- nb->nb_Next = NumberBlkChain;
- NumberBlkChain = nb;
- for(i = 0; i < (NUMBERBLK_SIZE - 1); i++)
- nb->nb_Numbers[i].num_Data.next = &nb->nb_Numbers[i + 1];
- nb->nb_Numbers[i].num_Data.next = NumberFreeList;
- NumberFreeList = nb->nb_Numbers;
- }
- num = NumberFreeList;
- }
- NumberFreeList = num->num_Data.next;
- num->num_Type = V_Number;
- num->num_Data.number = n;
- UsedNumbers++;
- DataAfterGC += sizeof(Number);
- return(num);
- }
- static void
- number_sweep(void)
- {
- NumberBlk *nb = NumberBlkChain;
- int i;
- NumberFreeList = NULL;
- UsedNumbers = 0;
- while(nb)
- {
- NumberBlk *nxt = nb->nb_Next;
- for(i = 0; i < NUMBERBLK_SIZE; i++)
- {
- if(!GC_MARKEDP(&nb->nb_Numbers[i]))
- {
- nb->nb_Numbers[i].num_Data.next = NumberFreeList;
- NumberFreeList = &nb->nb_Numbers[i];
- }
- else
- {
- GC_CLR(&nb->nb_Numbers[i]);
- UsedNumbers++;
- }
- }
- nb = nxt;
- }
- #ifdef STATIC_SMALL_NUMBERS
- for(i = 0; i < STATIC_SMALL_NUMBERS; i++)
- GC_CLR(&SmallNumbers[i]);
- #endif
- }
- int
- number_cmp(VALUE v1, VALUE v2)
- {
- if(VTYPE(v1) == VTYPE(v2))
- return(VNUM(v1) - VNUM(v2));
- return(1);
- }
-
- int
- ptr_cmp(VALUE v1, VALUE v2)
- {
- if(VTYPE(v1) == VTYPE(v2))
- return(!(VPTR(v1) == VPTR(v2)));
- return(1);
- }
-
- static ConsBlk *ConsBlkChain;
- static Cons *ConsFreeList;
- static int AllocatedCons, UsedCons;
-
- _PR VALUE cmd_cons(VALUE, VALUE);
- DEFUN("cons", cmd_cons, subr_cons, (VALUE car, VALUE cdr), V_Subr2, DOC_cons) /*
- ::doc:cons::
- (cons CAR-VALUE CDR-VALUE)
- Returns a new cons-cell with car CAR-VALUE and cdr CDR-VALUE.
- ::end:: */
- {
- Cons *cn = ConsFreeList;
- if(!cn)
- {
- ConsBlk *cb = mycalloc(sizeof(ConsBlk));
- if(cb)
- {
- int i;
- AllocatedCons += CONSBLK_SIZE;
- cb->cb_Next = ConsBlkChain;
- ConsBlkChain = cb;
- for(i = 0; i < (CONSBLK_SIZE - 1); i++)
- cb->cb_Cons[i].cn_Cdr = &cb->cb_Cons[i + 1];
- cb->cb_Cons[i].cn_Cdr = NULL;
- ConsFreeList = cb->cb_Cons;
- }
- cn = ConsFreeList;
- }
- ConsFreeList = cn->cn_Cdr;
- cn->cn_Type = V_Cons;
- cn->cn_Car = car;
- cn->cn_Cdr = cdr;
- UsedCons++;
- DataAfterGC += sizeof(Cons);
- return(cn);
- }
- void
- cons_free(VALUE cn)
- {
- VCDR(cn) = ConsFreeList;
- ConsFreeList = cn;
- UsedCons--;
- }
-
- static void
- cons_sweep(void)
- {
- ConsBlk *cb = ConsBlkChain;
- ConsBlkChain = NULL;
- ConsFreeList = NULL;
- UsedCons = 0;
- while(cb)
- {
- ConsBlk *nxt = cb->cb_Next;
- Cons *newfree = NULL, *newfreetail = NULL, *this;
- int i, newused = 0;
- for(i = 0, this = cb->cb_Cons; i < CONSBLK_SIZE; i++, this++)
- {
- if(!GC_MARKEDP(this))
- {
- if(!newfreetail)
- newfreetail = this;
- this->cn_Cdr = newfree;
- newfree = this;
- }
- else
- {
- GC_CLR(this);
- newused++;
- }
- }
- if(newused == 0)
- {
- /* Whole ConsBlk unused, lets get rid of it. */
- myfree(cb);
- AllocatedCons -= CONSBLK_SIZE;
- }
- else
- {
- if(newfreetail)
- {
- /* Link this mini-freelist onto the main one. */
- newfreetail->cn_Cdr = ConsFreeList;
- ConsFreeList = newfree;
- UsedCons += newused;
- }
- /* Have to rebuild the ConsBlk chain as well. */
- cb->cb_Next = ConsBlkChain;
- ConsBlkChain = cb;
- }
- cb = nxt;
- }
- }
- int
- cons_cmp(VALUE v1, VALUE v2)
- {
- int rc = 1;
- if(VTYPE(v1) == VTYPE(v2))
- {
- rc = VALUECMP(VCAR(v1), VCAR(v2));
- if(!rc)
- rc = valuecmp(VCDR(v1), VCDR(v2));
- }
- return(rc);
- }
-
- VALUE
- list_1(VALUE v1)
- {
- return(LIST_1(v1));
- }
- VALUE
- list_2(VALUE v1, VALUE v2)
- {
- return(LIST_2(v1, v2));
- }
- VALUE
- list_3(VALUE v1, VALUE v2, VALUE v3)
- {
- return(LIST_3(v1, v2, v3));
- }
- VALUE
- list_4(VALUE v1, VALUE v2, VALUE v3, VALUE v4)
- {
- return(LIST_4(v1, v2, v3, v4));
- }
- VALUE
- list_5(VALUE v1, VALUE v2, VALUE v3, VALUE v4, VALUE v5)
- {
- return(LIST_5(v1, v2, v3, v4, v5));
- }
-
- static Vector *VectorChain;
- static int UsedVectorSlots;
- Vector *
- newvector(int size)
- {
- int len = VECT_SIZE(size);
- Vector *v = mycalloc(len);
- if(v)
- {
- v->vc_Type = V_Vector;
- v->vc_Next = VectorChain;
- VectorChain = v;
- v->vc_Size = size;
- UsedVectorSlots += size;
- DataAfterGC += len;
- }
- return(v);
- }
- static void
- vector_sweep(void)
- {
- Vector *this = VectorChain;
- VectorChain = NULL;
- UsedVectorSlots = 0;
- while(this)
- {
- Vector *nxt = this->vc_Next;
- if(!GC_MARKEDP(this))
- myfree(this);
- else
- {
- this->vc_Next = VectorChain;
- VectorChain = this;
- UsedVectorSlots += this->vc_Size;
- GC_CLR(this);
- }
- this = nxt;
- }
- }
- int
- vector_cmp(VALUE v1, VALUE v2)
- {
- int rc = 1;
- if((VTYPE(v1) == VTYPE(v2)) && (VVECT(v1)->vc_Size == VVECT(v2)->vc_Size))
- {
- int i;
- for(i = rc = 0; (i < VVECT(v1)->vc_Size) && (!rc); i++)
- rc = valuecmp(&VVECT(v1)->vc_Array[i], &VVECT(v2)->vc_Array[i]);
- }
- return(rc);
- }
-
- static LPosBlk *LPosBlkChain;
- static LPos *LPosFreeList;
- static int UsedLPos, AllocatedLPos;
- LPos *
- newlpos(POS *pos)
- {
- LPos *lp = LPosFreeList;
- if(!lp)
- {
- LPosBlk *lb = mycalloc(sizeof(LPosBlk));
- if(lb)
- {
- int i;
- AllocatedLPos += LPOSBLK_SIZE;
- lb->lb_Next = LPosBlkChain;
- LPosBlkChain = lb;
- for(i = 0; i < (LPOSBLK_SIZE - 1); i++)
- lb->lb_Pos[i].lp_Next = &lb->lb_Pos[i + 1];
- lb->lb_Pos[i].lp_Next = LPosFreeList;
- LPosFreeList = lb->lb_Pos;
- }
- lp = LPosFreeList;
- }
- LPosFreeList = lp->lp_Next;
- lp->lp_Data.type = V_Pos;
- if(pos)
- lp->lp_Data.pos = *pos;
- UsedLPos++;
- DataAfterGC += sizeof(LPos);
- return(lp);
- }
- LPos *
- newlpos2(long x, long y)
- {
- POS tmp;
- tmp.pos_Col = x;
- tmp.pos_Line = y;
- return(newlpos(&tmp));
- }
- _PR VALUE cmd_pos(VALUE, VALUE);
- DEFUN("pos", cmd_pos, subr_pos, (VALUE x, VALUE y), V_Subr2, DOC_pos) /*
- ::doc:pos::
- (pos X Y)
- Returns a new position object with coordinates (X , Y).
- ::end:: */
- {
- POS tmp;
- if(NUMBERP(x))
- tmp.pos_Col = VNUM(x) - 1;
- else
- tmp.pos_Col = CurrVW->vw_CursorPos.pos_Col;
- if(NUMBERP(y))
- tmp.pos_Line = VNUM(y) - 1;
- else
- tmp.pos_Line = CurrVW->vw_CursorPos.pos_Line;
- return(newlpos(&tmp));
- }
- _PR VALUE cmd_dup_pos(VALUE pos);
- DEFUN("dup-pos", cmd_dup_pos, subr_dup_pos, (VALUE pos), V_Subr1, DOC_dup_pos) /*
- ::doc:dup_pos::
- (dup-pos POS)
- Returns a new copy of POS.
- ::end:: */
- {
- DECLARE1(pos, POSP);
- return(newlpos(&VPOS(pos)));
- }
- void
- lpos_prin(VALUE strm, VALUE obj)
- {
- u_char tbuf[32];
- sprintf(tbuf, "#<pos %ld %ld>", VPOS(obj).pos_Col + 1, VPOS(obj).pos_Line + 1);
- streamputs(strm, tbuf, FALSE);
- }
- static void
- lpos_sweep(void)
- {
- LPosBlk *lb = LPosBlkChain;
- LPosFreeList = NULL;
- UsedLPos = 0;
- while(lb)
- {
- int i;
- LPosBlk *nxt = lb->lb_Next;
- for(i = 0; i < LPOSBLK_SIZE; i++)
- {
- if(!GC_MARKEDP(&lb->lb_Pos[i]))
- {
- lb->lb_Pos[i].lp_Next = LPosFreeList;
- LPosFreeList = &lb->lb_Pos[i];
- }
- else
- {
- GC_CLR(&lb->lb_Pos[i]);
- UsedLPos++;
- }
- }
- lb = nxt;
- }
- }
- int
- lpos_cmp(VALUE v1, VALUE v2)
- {
- int rc = 1;
- if(VTYPE(v2) == VTYPE(v1))
- {
- if(!(rc = VPOS(v1).pos_Line - VPOS(v2).pos_Line))
- rc = VPOS(v1).pos_Col - VPOS(v2).pos_Col;
- }
- return(rc);
- }
-
- /*
- * Garbage Collection is here
- */
- #define NUM_STATIC_OBJS 128
- static VALUE *StaticMarks[NUM_STATIC_OBJS];
- static int NextStatic;
- _PR GCVAL *GCVStack;
- _PR GCVALN *GCVNStack;
- GCVAL *GCVStack;
- GCVALN *GCVNStack;
- /*
- * DataAfterGC = bytes of storage used since last gc
- * DataBeforeGC = value that DataAfterGC should be before gc'ing
- * IdleDataBeforeGC = value that DAGC should be before gc'ing in idle time
- * GCinhibit = protects against against gc in critical section when TRUE
- */
- _PR int DataAfterGC, DataBeforeGC, IdleDataBeforeGC, GCinhibit;
- int DataAfterGC, DataBeforeGC = 100000, IdleDataBeforeGC = 20000, GCinhibit;
-
- #ifdef GC_MONITOR_STK
- static int *StkHighTide;
- #endif
-
- void
- markstatic(VALUE *obj)
- {
- assert(NextStatic < NUM_STATIC_OBJS);
- StaticMarks[NextStatic++] = obj;
- }
-
- /* Mark a single Lisp object.
- This attempts to eliminate as much tail-recursion as possible (by
- changing the VAL and jumping back to the `again' label). */
- void
- markvalue(register VALUE val)
- {
- #ifdef GC_MONITOR_STK
- int dummy;
- /* Assumes that the stack grows downwards (towards 0) */
- if(&dummy < StkHighTide)
- StkHighTide = &dummy;
- #endif
- #if 0
- /* This is done in the macro MARKVAL(), it saves an unnecessary function
- call. */
- if((val == NULL) || GC_MARKEDP(val))
- return;
- #endif
- #ifdef MINSTACK
- /* This is a real problem. I can't safely stop marking since this means
- that some lisp data won't have been marked and therefore the sweep
- will screw up. But if I just keep on merrily recursing I risk
- blowing the stack. */
- if(STK_SIZE <= GC_MINSTACK)
- {
- STK_WARN("garbage-collect(major problem!)");
- /* Perhaps I should longjmp() back to the start of the gc, then quit
- totally? */
- return;
- }
- #endif
-
- again:
- switch(VTYPE(val))
- {
- case V_Cons:
- /* Attempts to walk though whole lists at a time (since Lisp
- lists mainly link from the cdr). */
- GC_SET(val);
- if(NILP(VCDR(val)))
- {
- /* End of a list. We can safely mark the car non-recursively. */
- val = VCAR(val);
- }
- else
- {
- MARKVAL(VCAR(val));
- val = VCDR(val);
- }
- if(val && !GC_MARKEDP(val))
- goto again;
- break;
-
- case V_Vector:
- {
- register int i;
- GC_SET(val);
- for(i = 0; i < VVECT(val)->vc_Size; i++)
- MARKVAL(VVECT(val)->vc_Array[i]);
- }
- break;
-
- case V_Symbol:
- GC_SET(val);
- MARKVAL(VSYM(val)->sym_Name);
- MARKVAL(VSYM(val)->sym_Value);
- MARKVAL(VSYM(val)->sym_Function);
- MARKVAL(VSYM(val)->sym_PropList);
- val = VSYM(val)->sym_Next;
- if(val && !GC_MARKEDP(val))
- goto again;
- break;
-
- case V_Keytab:
- {
- register int i;
- GC_SET(val);
- for(i = 0; i < 128; i++)
- {
- register Key *ky = VKEYTAB(val)->kt_Keys[i];
- while(ky)
- {
- MARKVAL(ky->ky_Form);
- ky = ky->ky_Link.next;
- }
- }
- }
- break;
-
- case V_Keylist:
- {
- register Key *nxtky, *ky = (Key *)VKEYLIST(val)->kl_List.mlh_Head;
- GC_SET(val);
- while((nxtky = (Key *)ky->ky_Link.node.mln_Succ))
- {
- MARKVAL(ky->ky_Form);
- ky = nxtky;
- }
- }
- break;
-
- case V_Buffer:
- GC_SET(val);
- MARKVAL(VTX(val)->tx_FileName);
- MARKVAL(VTX(val)->tx_BufferName);
- MARKVAL(VTX(val)->tx_ModeName);
- val = VTX(val)->tx_LocalVariables;
- if(!GC_MARKEDP(val) && !NILP(val))
- goto again;
- break;
-
- case V_Window:
- GC_SET(val);
- MARKVAL(VWIN(val)->vw_Tx);
- MARKVAL(VWIN(val)->vw_FontName);
- #ifdef HAVE_AMIGA
- MARKVAL(VWIN(val)->vw_WindowSys.ws_ScreenName);
- #endif
- val = VWIN(val)->vw_LocalVariables;
- if(!GC_MARKEDP(val) && !NILP(val))
- goto again;
- break;
-
- case V_File:
- GC_SET(val);
- MARKVAL(VFILE(val)->lf_Name);
- break;
-
- case V_Process:
- GC_SET(val);
- #ifdef HAVE_UNIX
- proc_mark(val);
- #endif
- break;
-
- case V_Mark:
- GC_SET(val);
- if(!VMARK(val)->mk_Resident)
- {
- /* TXs don't get marked here. They should still be able to
- be gc'd if there's marks pointing to them. The marks will
- just get made non-resident. */
- MARKVAL(VMARK(val)->mk_File.name);
- }
- MARKVAL(VMARK(val)->mk_Pos);
- break;
-
- case V_String:
- case V_Number:
- case V_Pos:
- GC_SET(val);
- break;
-
- case V_StaticString:
- case V_Var:
- case V_Subr0:
- case V_Subr1:
- case V_Subr2:
- case V_Subr3:
- case V_Subr4:
- case V_Subr5:
- case V_SubrN:
- case V_SF:
- }
- }
-
- _PR VALUE var_garbage_threshold(VALUE val);
- DEFUN("garbage-threshold", var_garbage_threshold, subr_garbage_threshold, (VALUE val), V_Var, DOC_garbage_threshold) /*
- ::doc:garbage_threshold::
- The number of bytes of storage which must be used before a garbage-
- collection is triggered.
- ::end:: */
- {
- if(val)
- {
- if(NUMBERP(val))
- DataBeforeGC = VNUM(val);
- return(NULL);
- }
- return(newnumber(DataBeforeGC));
- }
-
- _PR VALUE var_idle_garbage_threshold(VALUE val);
- DEFUN("idle-garbage-threshold", var_idle_garbage_threshold, subr_idle_garbage_threshold, (VALUE val), V_Var, DOC_idle_garbage_threshold) /*
- ::doc:idle_garbage_threshold::
- The number of bytes of storage which must be used before a garbage-
- collection is triggered when the editor is idle.
- ::end:: */
- {
- if(val)
- {
- if(NUMBERP(val))
- IdleDataBeforeGC = VNUM(val);
- return(NULL);
- }
- return(newnumber(IdleDataBeforeGC));
- }
-
- _PR VALUE cmd_garbage_collect(VALUE noStats);
- DEFUN("garbage-collect", cmd_garbage_collect, subr_garbage_collect, (VALUE noStats), V_Subr1, DOC_garbage_collect) /*
- ::doc:garbage_collect::
- (garbage-collect)
- Scans all allocated storage for unusable data, and puts it onto the free-
- list. This is done automatically when the amount of storage used since the
- last garbage-collection is greater than `garbage-threshold'.
- ::end:: */
- {
- int i;
- GCVAL *gcv;
- GCVALN *gcvn;
- VW *vw;
- struct LispCall *lc;
-
- #ifdef GC_MONITOR_STK
- int dummy;
- StkHighTide = &dummy;
- #endif
-
- if(GCinhibit)
- return(sym_nil);
-
- #ifdef HAVE_UNIX
- /* Make sure nothing plays with process structs while gc'ing */
- protect_procs();
- #endif
-
- streamputs(sym_t, "Garbage collecting...", FALSE);
- setvwtitle(CurrVW);
- #ifdef HAVE_X11
- XFlush(XDisplay);
- #endif
-
- /* mark static objects */
- for(i = 0; i < NextStatic; i++)
- MARKVAL(*StaticMarks[i]);
- /* mark stack based objects protected from GC */
- for(gcv = GCVStack; gcv; gcv = gcv->gcv_Next)
- MARKVAL(*gcv->gcv_Value);
- for(gcvn = GCVNStack; gcvn; gcvn = gcvn->gcv_Next)
- {
- for(i = 0; i < gcvn->gcv_N; i++)
- MARKVAL(gcvn->gcv_First[i]);
- }
-
- /* Don't want any open windows mysteriously vanishing so, */
- vw = ViewChain;
- while(vw)
- {
- if(vw->vw_Window)
- MARKVAL(vw);
- vw = vw->vw_Next;
- }
-
- #ifdef AMIGA
- /* Mark the strings in the menu strip. */
- ami_mark_menus();
- #endif
-
- /* have to mark the Lisp backtrace. */
- lc = LispCallStack;
- while(lc)
- {
- MARKVAL(lc->lc_Fun);
- MARKVAL(lc->lc_Args);
- /* don't bother marking `lc_ArgsEvalledP' it's always `nil' or `t' */
- lc = lc->lc_Next;
- }
-
- string_sweep();
- number_sweep();
- cons_sweep();
- vector_sweep();
- lpos_sweep();
- symbol_sweep();
- file_sweep();
- buffer_sweep();
- mark_sweep();
- window_sweep();
- keymap_sweep();
- #ifdef HAVE_UNIX
- proc_sweep();
- #endif
-
- streamputs(sym_t, "done.", FALSE);
- setvwtitle(CurrVW);
- CurrVW->vw_Flags &= ~VWFF_REFRESH_STATUS;
- #ifdef HAVE_X11
- XFlush(XDisplay);
- #endif
-
- #ifdef HAVE_UNIX
- /* put SIGCHLD back to normal */
- unprotect_procs();
- #endif
-
- DataAfterGC = 0;
-
- #ifdef GC_MONITOR_STK
- fprintf(stderr, "gc: stack usage = %d\n",
- ((int)&dummy) - (int)StkHighTide);
- #endif
-
- if(NILP(noStats))
- {
- return(list_5(
- cmd_cons(newnumber(UsedCons), newnumber(AllocatedCons - UsedCons)),
- cmd_cons(newnumber(UsedNumbers), newnumber(AllocatedNumbers - UsedNumbers - 1)),
- cmd_cons(newnumber(UsedSymbols), newnumber(AllocatedSymbols - UsedSymbols)),
- cmd_cons(newnumber(UsedLPos), newnumber(AllocatedLPos - UsedLPos)),
- newnumber(UsedVectorSlots)));
- }
- return(sym_t);
- }
-
- void
- values_init(void)
- {
- #ifdef STATIC_SMALL_NUMBERS
- int i;
- for(i = 0; i < STATIC_SMALL_NUMBERS; i++)
- {
- SmallNumbers[i].num_Type = V_Number;
- SmallNumbers[i].num_Data.number = i;
- }
- #endif
- LispStrMem.sm_UseMallocChain = TRUE;
- sm_init(&LispStrMem);
- }
- void
- values_init2(void)
- {
- ADD_SUBR(subr_cons);
- ADD_SUBR(subr_pos);
- ADD_SUBR(subr_dup_pos);
- ADD_SUBR(subr_garbage_threshold);
- ADD_SUBR(subr_idle_garbage_threshold);
- ADD_SUBR(subr_garbage_collect);
- }
- void
- values_kill(void)
- {
- ConsBlk *cb = ConsBlkChain;
- NumberBlk *nb = NumberBlkChain;
- Vector *v = VectorChain;
- LPosBlk *lb = LPosBlkChain;
- while(cb)
- {
- ConsBlk *nxt = cb->cb_Next;
- myfree(cb);
- cb = nxt;
- }
- while(nb)
- {
- NumberBlk *nxt = nb->nb_Next;
- myfree(nb);
- nb = nxt;
- }
- while(v)
- {
- Vector *nxt = v->vc_Next;
- myfree(v);
- v = nxt;
- }
- while(lb)
- {
- LPosBlk *nxt = lb->lb_Next;
- myfree(lb);
- lb = nxt;
- }
- sm_kill(&LispStrMem);
- }
-