home *** CD-ROM | disk | FTP | other *** search
- /* Lisp garbage collections : uses copy/free algorithm
- Places to check :
- symbol
- values
- functions
- names
- stack
-
-
-
-
- */
- #include <stdlib.h>
- #include "lisp.hpp"
-
- #ifdef NO_LIBS
- #include "fakelib.hpp"
- #else
- #include "jmalloc.hpp"
- #include "macs.hpp"
- #include "dprint.hpp"
- #endif
-
- #include "stack.hpp"
-
- #include <string.h>
-
-
- grow_stack<void> l_user_stack(600); // stack user progs can push data and have it GCed
- grow_stack<void *> l_ptr_stack(6000); // stack of user pointers, user pointers get remapped on GC
-
- int reg_ptr_total=0;
- int reg_ptr_list_size=0;
- void ***reg_ptr_list=NULL;
-
- void register_pointer(void **addr)
- {
- if (reg_ptr_total>=reg_ptr_list_size)
- {
- reg_ptr_list_size+=0x100;
- reg_ptr_list=(void ***)jrealloc(reg_ptr_list,sizeof(void **)*reg_ptr_list_size,"registered ptr list");
- }
- reg_ptr_list[reg_ptr_total++]=addr;
- }
-
-
- void unregister_pointer(void **addr)
- {
- int i;
- void ***reg_on=reg_ptr_list;
- for (i=0;i<reg_ptr_total;i++,reg_on++)
- {
- if (*reg_on==addr)
- {
- int j;
- reg_ptr_total--;
- for (j=i;j<reg_ptr_total;j++,reg_on++)
- reg_on[0]=reg_on[1];
- return ;
- }
- }
- dprintf("Unable to locate ptr to unregister");
- }
-
- static void *collect_object(void *x);
- static void *collect_array(void *x)
- {
- long s=((lisp_1d_array *)x)->size;
- lisp_1d_array *a=new_lisp_1d_array(s,NULL);
- void **src,**dst;
- src=(void **)(((lisp_1d_array *)x)+1);
- dst=(void **)(a+1);
- for (int i=0;i<s;i++)
- dst[i]=collect_object(src[i]);
-
- return a;
- }
-
- static uchar *cstart,*cend,*collected_start,*collected_end;
-
- inline void *collect_cons_cell(void *x)
- {
- cons_cell *last=NULL,*first;
- if (!x) return x;
- for (;x && item_type(x)==L_CONS_CELL;)
- {
- cons_cell *p=new_cons_cell();
- void *old_car=((cons_cell *)x)->car;
- void *old_cdr=((cons_cell *)x)->cdr;
- void *old_x=x;
- x=CDR(x);
- ((lisp_collected_object *)old_x)->type=L_COLLECTED_OBJECT;
- ((lisp_collected_object *)old_x)->new_reference=p;
-
- p->car=collect_object(old_car);
- p->cdr=collect_object(old_cdr);
-
- if (last) last->cdr=p;
- else first=p;
- last=p;
- }
- if (x)
- last->cdr=collect_object(x);
- return first; // we already set the collection pointers
- }
-
- static void *collect_object(void *x)
- {
- void *ret=x;
-
- if (((uchar *)x)>=cstart && ((uchar *)x)<cend)
- {
- switch (item_type(x))
- {
- case L_BAD_CELL :
- { lbreak("error : GC corrupted cell\n"); } break;
-
- case L_NUMBER :
- { ret=new_lisp_number(((lisp_number *)x)->num); } break;
-
-
- case L_SYS_FUNCTION :
- { ret=new_lisp_sys_function( ((lisp_sys_function *)x)->min_args,
- ((lisp_sys_function *)x)->max_args,
- ((lisp_sys_function *)x)->fun_number);
- } break;
- case L_USER_FUNCTION :
- {
- #ifndef NO_LIBS
- ret=new_lisp_user_function( ((lisp_user_function *)x)->alist,
- ((lisp_user_function *)x)->blist);
-
- #else
- void *arg=collect_object(((lisp_user_function *)x)->arg_list);
- void *block=collect_object(((lisp_user_function *)x)->block_list);
- ret=new_lisp_user_function(arg,block);
- #endif
- } break;
- case L_STRING :
- { ret=new_lisp_string(lstring_value(x)); } break;
-
- case L_CHARACTER :
- { ret=new_lisp_character(lcharacter_value(x)); } break;
-
- case L_C_FUNCTION :
- {
- ret=new_lisp_c_function( ((lisp_sys_function *)x)->min_args,
- ((lisp_sys_function *)x)->max_args,
- ((lisp_sys_function *)x)->fun);
- } break;
-
- case L_C_BOOL :
- {
- ret=new_lisp_c_bool( ((lisp_sys_function *)x)->min_args,
- ((lisp_sys_function *)x)->max_args,
- ((lisp_sys_function *)x)->fun);
- } break;
- case L_L_FUNCTION :
- {
- ret=new_user_lisp_function( ((lisp_sys_function *)x)->min_args,
- ((lisp_sys_function *)x)->max_args,
- ((lisp_sys_function *)x)->fun_number);
- } break;
-
- case L_POINTER :
- { ret=new_lisp_pointer(lpointer_value(x)); } break;
-
-
- case L_1D_ARRAY :
- { ret=collect_array(x); } break;
-
- case L_FIXED_POINT :
- { ret=new_lisp_fixed_point(lfixed_point_value(x)); } break;
-
- case L_CONS_CELL :
- { ret=collect_cons_cell((cons_cell *)x); } break;
-
- case L_OBJECT_VAR :
- {
- ret=new_lisp_object_var( ((lisp_object_var *)x)->number);
- } break;
- case L_COLLECTED_OBJECT :
- {
- ret=((lisp_collected_object *)x)->new_reference;
- } break;
-
- default :
- { lbreak("shouldn't happen. collecting bad object\n"); } break;
- }
- ((lisp_collected_object *)x)->type=L_COLLECTED_OBJECT;
- ((lisp_collected_object *)x)->new_reference=ret;
- } else if ((uchar *)x<collected_start || (uchar *)x>=collected_end)
- {
- if (item_type(x)==L_CONS_CELL) // still need to remap cons_cells outside of space
- {
- for (;x && item_type(x)==L_CONS_CELL;x=CDR(x))
- ((cons_cell *)x)->car=collect_object(((cons_cell *)x)->car);
- if (x)
- ((cons_cell *)x)->cdr=collect_object(((cons_cell *)x)->cdr);
- }
- }
-
- return ret;
- }
-
- static void collect_symbols(lisp_symbol *root)
- {
- if (root)
- {
- root->value=collect_object(root->value);
- root->function=collect_object(root->function);
- root->name=collect_object(root->name);
- collect_symbols(root->left);
- collect_symbols(root->right);
- }
- }
-
- static void collect_stacks()
- {
- long t=l_user_stack.son;
- void **d=l_user_stack.sdata;
- int i=0;
- for (;i<t;i++,d++)
- *d=collect_object(*d);
-
- t=l_ptr_stack.son;
- void ***d2=l_ptr_stack.sdata;
- for (i=0;i<t;i++,d2++)
- {
- void **ptr=*d2;
- *ptr=collect_object(*ptr);
- }
-
- d2=reg_ptr_list;
- for (t=0;t<reg_ptr_total;t++,d2++)
- {
- void **ptr=*d2;
- *ptr=collect_object(*ptr);
- }
-
- }
-
- void collect_space(int which_space) // should be tmp or permenant
- {
- int old_space=current_space;
- cstart=(uchar *)space[which_space];
- cend=(uchar *)free_space[which_space];
-
- space_size[GC_SPACE]=space_size[which_space];
- void *new_space=jmalloc(space_size[GC_SPACE],"collect lisp space");
- current_space=GC_SPACE;
- free_space[GC_SPACE]=space[GC_SPACE]=(char *)new_space;
-
- collected_start=(uchar *)new_space;
- collected_end=(((uchar *)new_space)+space_size[GC_SPACE]);
-
- collect_symbols(lsym_root);
- collect_stacks();
-
- memset(space[which_space],0,space_size[which_space]); // for debuging clear it out
- jfree(space[which_space]);
-
- space[which_space]=(char *)new_space;
- free_space[which_space]=((char *)new_space)+
- (((uchar *)free_space[GC_SPACE])-((uchar *)space[GC_SPACE]));
- current_space=old_space;
- }
-
-