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 <stdlib.h>
- #include <assert.h>
-
- #ifdef NEED_MEMORY_H
- # include <memory.h>
- #endif
-
- /* #define GC_MONITOR_STK */
-
- #define STATIC_SMALL_NUMBERS 256
-
- _PR int value_cmp(VALUE, VALUE);
- _PR void princ_val(VALUE, VALUE);
- _PR void print_val(VALUE, VALUE);
- _PR int nil_cmp(VALUE, VALUE);
- _PR VALUE make_string(int);
- _PR VALUE string_dupn(const u_char *, int);
- _PR VALUE string_dup(const u_char *);
- _PR int string_cmp(VALUE, VALUE);
- _PR bool set_string_len(VALUE, long);
- _PR VALUE make_number(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 VALUE make_vector(int);
- _PR VALUE make_lpos(POS *);
- _PR VALUE make_lpos2(long, long);
- _PR int lpos_cmp(VALUE, VALUE);
- _PR void lpos_prin(VALUE, VALUE);
- _PR int vector_cmp(VALUE, VALUE);
-
- _PR void mark_static(VALUE *);
- _PR void mark_value(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, 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_SUBPROCESSES
- { ptr_cmp, proc_prin, proc_prin, MKSTR("process") },
- #else
- { nil_cmp, lisp_prin, lisp_prin, MKSTR("process") },
- #endif
- { ptr_cmp, glyphtable_prin, glyphtable_prin, MKSTR("glyph-table") },
- { nil_cmp, lisp_prin, lisp_prin, MKSTR("void") },
- };
-
- int
- value_cmp(VALUE v1, VALUE v2)
- {
- if(v1 && v2)
- {
- /* If the two objects are the same object then they must be
- equivalent :-) */
- return(v1 == v2 ? 0 : VALUE_CMP(v1, v2));
- }
- return(1);
- }
-
- void
- princ_val(VALUE strm, VALUE val)
- {
- if(val)
- PRINC_VAL(strm, val);
- }
-
- void
- print_val(VALUE strm, VALUE val)
- {
- if(val)
- PRINT_VAL(strm, val);
- }
-
- int
- nil_cmp(VALUE val1, VALUE val2)
- {
- if(VTYPE(val1) == VTYPE(val2))
- return(0);
- return(1);
- }
-
- static StrMem lisp_strmem;
- _PR VALUE null_string;
- VALUE null_string = MKSTR("");
-
- /* Return a string object with room for exactly LEN characters. No extra
- byte is allocated for a zero terminator; do this manually if required. */
- VALUE
- make_string(int len)
- {
- DynamicString *str;
- int memlen = DSTR_SIZE(len);
- str = sm_alloc(&lisp_strmem, memlen);
- if(str)
- {
- str->ds_Length = len - 1;
- str->ds_Mem[0] = V_DynamicString;
- data_after_gc += memlen;
- return(VAL(&str->ds_Mem[0]));
- }
- return(NULL);
- }
-
- VALUE
- string_dupn(const u_char *src, int slen)
- {
- String *dst = VSTRING(make_string(slen + 1));
- if(dst)
- {
- memcpy(dst->str_Mem + 1, src, slen);
- dst->str_Mem[slen+1] = 0;
- }
- return(VAL(dst));
- }
-
- VALUE
- string_dup(const u_char * src)
- {
- return(string_dupn(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 = &lisp_strmem.sm_MemBuckets[bucket].mbu_FreeList;
- MemBlock *mbl = (MemBlock *)lisp_strmem.sm_MemBuckets[bucket].mbu_MemBlocks.mlh_Head;
- MemBlock *nxt;
- int chnksiz = MCHNK_SIZE((bucket + 1) * GRAIN);
- int numchnks = lisp_strmem.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)
- {
- register DynamicString *ds = (DynamicString *)mc->mc_Mem.mem;
- if(ds->ds_Mem[0] & GC_MARK_BIT)
- ds->ds_Mem[0] &= ~GC_MARK_BIT;
- else
- {
- mc->mc_BlkType = MBT_FREE;
- mc->mc_Mem.nextfree = *freelist;
- *freelist = mc;
- }
- }
- mc = (MemChunk *)((char *)mc + chnksiz);
- }
- mbl = nxt;
- }
- }
- mlc = lisp_strmem.sm_MallocChain;
- lisp_strmem.sm_MallocChain = NULL;
- while(mlc)
- {
- MemChunk *nxtmlc = mlc->mc_Header.next;
- register DynamicString *ds = (DynamicString *)mlc->mc_Mem.mem;
- if(ds->ds_Mem[0] == V_DynamicString)
- myfree(mlc);
- else
- {
- ds->ds_Mem[0] = V_DynamicString;
- mlc->mc_Header.next = lisp_strmem.sm_MallocChain;
- lisp_strmem.sm_MallocChain = mlc;
- }
- mlc = nxtmlc;
- }
- }
-
- /* Sets the length-field of the dynamic string STR to LEN. */
- bool
- set_string_len(VALUE str, long len)
- {
- if(VTYPEP(str, V_DynamicString))
- {
- DSTRING_HDR(str)->ds_Length = len;
- return(TRUE);
- }
- return(FALSE);
- }
-
- static NumberBlk *number_block_chain;
- static Number *number_freelist;
- static int allocated_numbers, used_numbers;
-
- #ifdef STATIC_SMALL_NUMBERS
- static Number small_numbers[STATIC_SMALL_NUMBERS];
- #endif
-
- VALUE
- make_number(long n)
- {
- Number *num;
- #ifdef STATIC_SMALL_NUMBERS
- if((n < STATIC_SMALL_NUMBERS) && (n >= 0))
- return(VAL(&small_numbers[n]));
- #endif
- if(!(num = number_freelist))
- {
- NumberBlk *nb = mymalloc(sizeof(NumberBlk));
- if(nb)
- {
- int i;
- allocated_numbers += NUMBERBLK_SIZE;
- nb->nb_Next = number_block_chain;
- number_block_chain = 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 = number_freelist;
- number_freelist = nb->nb_Numbers;
- }
- num = number_freelist;
- }
- number_freelist = num->num_Data.next;
- num->num_Type = V_Number;
- num->num_Data.number = n;
- used_numbers++;
- data_after_gc += sizeof(Number);
- return(VAL(num));
- }
-
- static void
- number_sweep(void)
- {
- NumberBlk *nb = number_block_chain;
- int i;
- number_freelist = NULL;
- used_numbers = 0;
- while(nb)
- {
- NumberBlk *nxt = nb->nb_Next;
- for(i = 0; i < NUMBERBLK_SIZE; i++)
- {
- if(!GC_MARKEDP(VAL(&nb->nb_Numbers[i])))
- {
- nb->nb_Numbers[i].num_Data.next = number_freelist;
- number_freelist = &nb->nb_Numbers[i];
- }
- else
- {
- GC_CLR(VAL(&nb->nb_Numbers[i]));
- used_numbers++;
- }
- }
- nb = nxt;
- }
- #ifdef STATIC_SMALL_NUMBERS
- for(i = 0; i < STATIC_SMALL_NUMBERS; i++)
- GC_CLR(VAL(&small_numbers[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 *cons_block_chain;
- static Cons *cons_freelist;
- static int allocated_cons, used_cons;
-
- _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;
- cn = cons_freelist;
- if(!cn)
- {
- ConsBlk *cb = mycalloc(sizeof(ConsBlk));
- if(cb)
- {
- int i;
- allocated_cons += CONSBLK_SIZE;
- cb->cb_Next = cons_block_chain;
- cons_block_chain = cb;
- for(i = 0; i < (CONSBLK_SIZE - 1); i++)
- cb->cb_Cons[i].cn_Cdr = VAL(&cb->cb_Cons[i + 1]);
- cb->cb_Cons[i].cn_Cdr = NULL;
- cons_freelist = cb->cb_Cons;
- }
- cn = cons_freelist;
- }
- cons_freelist = VCONS(cn->cn_Cdr);
- cn->cn_Type = V_Cons;
- cn->cn_Car = car;
- cn->cn_Cdr = cdr;
- used_cons++;
- data_after_gc += sizeof(Cons);
- return(VAL(cn));
- }
-
- void
- cons_free(VALUE cn)
- {
- VCDR(cn) = VAL(cons_freelist);
- cons_freelist = VCONS(cn);
- used_cons--;
- }
-
- static void
- cons_sweep(void)
- {
- ConsBlk *cb = cons_block_chain;
- cons_block_chain = NULL;
- cons_freelist = NULL;
- used_cons = 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(VAL(this)))
- {
- if(!newfreetail)
- newfreetail = this;
- this->cn_Cdr = VAL(newfree);
- newfree = this;
- }
- else
- {
- GC_CLR(VAL(this));
- newused++;
- }
- }
- if(newused == 0)
- {
- /* Whole ConsBlk unused, lets get rid of it. */
- myfree(cb);
- allocated_cons -= CONSBLK_SIZE;
- }
- else
- {
- if(newfreetail)
- {
- /* Link this mini-freelist onto the main one. */
- newfreetail->cn_Cdr = VAL(cons_freelist);
- cons_freelist = newfree;
- used_cons += newused;
- }
- /* Have to rebuild the ConsBlk chain as well. */
- cb->cb_Next = cons_block_chain;
- cons_block_chain = cb;
- }
- cb = nxt;
- }
- }
-
- int
- cons_cmp(VALUE v1, VALUE v2)
- {
- int rc = 1;
- if(VTYPE(v1) == VTYPE(v2))
- {
- rc = value_cmp(VCAR(v1), VCAR(v2));
- if(!rc)
- rc = value_cmp(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 *vector_chain;
- static int used_vector_slots;
-
- VALUE
- make_vector(int size)
- {
- int len = VECT_SIZE(size);
- Vector *v = mycalloc(len);
- if(v)
- {
- v->vc_Type = V_Vector;
- v->vc_Next = vector_chain;
- vector_chain = v;
- v->vc_Size = size;
- used_vector_slots += size;
- data_after_gc += len;
- }
- return(VAL(v));
- }
-
- static void
- vector_sweep(void)
- {
- Vector *this = vector_chain;
- vector_chain = NULL;
- used_vector_slots = 0;
- while(this)
- {
- Vector *nxt = this->vc_Next;
- if(!GC_MARKEDP(VAL(this)))
- myfree(this);
- else
- {
- this->vc_Next = vector_chain;
- vector_chain = this;
- used_vector_slots += this->vc_Size;
- GC_CLR(VAL(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 = value_cmp(VVECT(v1)->vc_Array[i], VVECT(v2)->vc_Array[i]);
- }
- return(rc);
- }
-
- static LPosBlk *lpos_block_chain;
- static LPos *lpos_free_list;
- static int used_lpos, allocated_lpos;
-
- VALUE
- make_lpos(POS *pos)
- {
- LPos *lp = lpos_free_list;
- if(!lp)
- {
- LPosBlk *lb = mycalloc(sizeof(LPosBlk));
- if(lb)
- {
- int i;
- allocated_lpos += LPOSBLK_SIZE;
- lb->lb_Next = lpos_block_chain;
- lpos_block_chain = 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 = lpos_free_list;
- lpos_free_list = lb->lb_Pos;
- }
- lp = lpos_free_list;
- }
- lpos_free_list = lp->lp_Next;
- lp->lp_Data.type = V_Pos;
- if(pos)
- lp->lp_Data.pos = *pos;
- used_lpos++;
- data_after_gc += sizeof(LPos);
- return(VAL(lp));
- }
-
- VALUE
- make_lpos2(long x, long y)
- {
- POS tmp;
- tmp.pos_Col = x;
- tmp.pos_Line = y;
- return(make_lpos(&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);
- else
- tmp.pos_Col = curr_vw->vw_CursorPos.pos_Col;
- if(NUMBERP(y))
- tmp.pos_Line = VNUM(y);
- else
- tmp.pos_Line = curr_vw->vw_CursorPos.pos_Line;
- return(make_lpos(&tmp));
- }
-
- _PR VALUE cmd_copy_pos(VALUE pos);
- DEFUN("copy-pos", cmd_copy_pos, subr_copy_pos, (VALUE pos), V_Subr1, DOC_copy_pos) /*
- ::doc:copy_pos::
- copy-pos POS
-
- Returns a new copy of POS.
- ::end:: */
- {
- DECLARE1(pos, POSP);
- return(make_lpos(&VPOS(pos)));
- }
-
- void
- lpos_prin(VALUE strm, VALUE obj)
- {
- u_char tbuf[32];
- sprintf(tbuf, "#<pos %ld %ld>", VPOS(obj).pos_Col, VPOS(obj).pos_Line);
- stream_puts(strm, tbuf, -1, FALSE);
- }
-
- static void
- lpos_sweep(void)
- {
- LPosBlk *lb = lpos_block_chain;
- lpos_free_list = NULL;
- used_lpos = 0;
- while(lb)
- {
- int i;
- LPosBlk *nxt = lb->lb_Next;
- for(i = 0; i < LPOSBLK_SIZE; i++)
- {
- if(!GC_MARKEDP(VAL(&lb->lb_Pos[i])))
- {
- lb->lb_Pos[i].lp_Next = lpos_free_list;
- lpos_free_list = &lb->lb_Pos[i];
- }
- else
- {
- GC_CLR(VAL(&lb->lb_Pos[i]));
- used_lpos++;
- }
- }
- 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 *static_marks[NUM_STATIC_OBJS];
- static int next_static;
-
- _PR GCVAL *gcv_stack;
- _PR GCVALN *gcvn_stack;
- GCVAL *gcv_stack;
- GCVALN *gcvn_stack;
-
- /* data_after_gc = bytes of storage used since last gc
- gc_threshold = value that data_after_gc should be before gc'ing
- idle_gc_threshold = value that DAGC should be before gc'ing in idle time
- gc_inhibit = protects against against gc in critical section when TRUE */
- _PR int data_after_gc, gc_threshold, idle_gc_threshold, gc_inhibit;
- int data_after_gc, gc_threshold = 100000, idle_gc_threshold = 20000, gc_inhibit;
-
- #ifdef GC_MONITOR_STK
- static int *gc_stack_high_tide;
- #endif
-
- void
- mark_static(VALUE *obj)
- {
- assert(next_static < NUM_STATIC_OBJS);
- static_marks[next_static++] = 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
- mark_value(register VALUE val)
- {
- #ifdef GC_MONITOR_STK
- int dummy;
- /* Assumes that the stack grows downwards (towards 0) */
- if(&dummy < gc_stack_high_tide)
- gc_stack_high_tide = &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 GC_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_Buffer:
- GC_SET(val);
- MARKVAL(VTX(val)->tx_FileName);
- MARKVAL(VTX(val)->tx_BufferName);
- MARKVAL(VTX(val)->tx_ModeName);
- MARKVAL(VTX(val)->tx_MinorModeNameList);
- MARKVAL(VTX(val)->tx_MinorModeNameString);
- MARKVAL(VTX(val)->tx_GlyphTable);
- MARKVAL(VTX(val)->tx_UndoList);
- MARKVAL(VTX(val)->tx_ToUndoList);
- MARKVAL(VTX(val)->tx_UndoneList);
- val = VTX(val)->tx_LocalVariables;
- if(!GC_MARKEDP(val) && !NILP(val))
- goto again;
- break;
-
- case V_Window:
- GC_SET(val);
- MARKVAL(VAL(VWIN(val)->vw_Tx));
- MARKVAL(VWIN(val)->vw_FontName);
- #ifdef HAVE_AMIGA
- MARKVAL(VWIN(val)->vw_WindowSys.ws_ScreenName);
- #endif
- val = VWIN(val)->vw_BufferList;
- 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_SUBPROCESSES
- 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_DynamicString:
- case V_Number:
- case V_Pos:
- case V_GlyphTable:
- 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))
- gc_threshold = VNUM(val);
- return(NULL);
- }
- return(make_number(gc_threshold));
- }
-
- _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))
- idle_gc_threshold = VNUM(val);
- return(NULL);
- }
- return(make_number(idle_gc_threshold));
- }
-
- _PR VALUE cmd_garbage_collect(VALUE noStats);
- DEFUN_INT("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;
- gc_stack_high_tide = &dummy;
- #endif
-
- if(gc_inhibit)
- return(sym_nil);
-
- #ifdef HAVE_SUBPROCESSES
- /* Make sure nothing plays with process structs while gc'ing */
- protect_procs();
- #endif
-
- #if 0
- stream_puts(sym_t, "Garbage collecting...", -1, FALSE);
- refresh_message(curr_vw);
- #ifdef HAVE_X11
- XFlush(x11_display);
- #endif
- #endif
-
- /* gc the undo lists */
- undo_trim();
-
- /* mark static objects */
- for(i = 0; i < next_static; i++)
- MARKVAL(*static_marks[i]);
- /* mark stack based objects protected from GC */
- for(gcv = gcv_stack; gcv; gcv = gcv->gcv_Next)
- MARKVAL(*gcv->gcv_Value);
- for(gcvn = gcvn_stack; 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 = view_chain;
- while(vw)
- {
- if(vw->vw_Window)
- MARKVAL(VAL(vw));
- vw = vw->vw_Next;
- }
-
- #ifdef HAVE_AMIGA
- /* Mark the strings in the menu strip. */
- ami_mark_menus();
- #endif
-
- /* have to mark the Lisp backtrace. */
- lc = lisp_call_stack;
- 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();
- #ifdef HAVE_SUBPROCESSES
- proc_sweep();
- #endif
- glyphtable_sweep();
-
- #if 0
- stream_puts(sym_t, "done.", -1, FALSE);
- refresh_message(curr_vw);
- curr_vw->vw_Flags &= ~VWFF_REFRESH_STATUS;
- #ifdef HAVE_X11
- XFlush(x11_display);
- #endif
- #endif
-
- /* This seems an ideal time to reclaim any general strings... */
- sm_flush(&main_strmem);
-
- #ifdef HAVE_SUBPROCESSES
- /* put SIGCHLD back to normal */
- unprotect_procs();
- #endif
-
- data_after_gc = 0;
-
- #ifdef GC_MONITOR_STK
- fprintf(stderr, "gc: stack usage = %d\n",
- ((int)&dummy) - (int)gc_stack_high_tide);
- #endif
-
- if(NILP(noStats))
- {
- return(list_5(cmd_cons(make_number(used_cons),
- make_number(allocated_cons - used_cons)),
- cmd_cons(make_number(used_numbers),
- make_number(allocated_numbers-used_numbers-1)),
- cmd_cons(make_number(used_symbols),
- make_number(allocated_symbols - used_symbols)),
- cmd_cons(make_number(used_lpos),
- make_number(allocated_lpos - used_lpos)),
- make_number(used_vector_slots)));
- }
- return(sym_t);
- }
-
- void
- values_init(void)
- {
- #ifdef STATIC_SMALL_NUMBERS
- register int i;
- for(i = 0; i < STATIC_SMALL_NUMBERS; i++)
- {
- small_numbers[i].num_Type = V_Number;
- small_numbers[i].num_Data.number = i;
- }
- #endif
- lisp_strmem.sm_UseMallocChain = TRUE;
- sm_init(&lisp_strmem);
- }
-
- void
- values_init2(void)
- {
- ADD_SUBR(subr_cons);
- ADD_SUBR(subr_pos);
- ADD_SUBR(subr_copy_pos);
- ADD_SUBR(subr_garbage_threshold);
- ADD_SUBR(subr_idle_garbage_threshold);
- ADD_SUBR(subr_garbage_collect);
- }
-
- void
- values_kill(void)
- {
- ConsBlk *cb = cons_block_chain;
- NumberBlk *nb = number_block_chain;
- Vector *v = vector_chain;
- LPosBlk *lb = lpos_block_chain;
- 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;
- }
- cons_block_chain = NULL;
- number_block_chain = NULL;
- vector_chain = NULL;
- lpos_block_chain = NULL;
- sm_kill(&lisp_strmem);
- }
-