home *** CD-ROM | disk | FTP | other *** search
- /* ******************************************************************** */
- /* copy.c copyright (c) university of bath 1992 */
- /* */
- /* creation of modules */
- /* ******************************************************************** */
-
- /*
- * $Id: copy.c,v 1.32 1992/06/18 10:02:09 pab Exp pab $
- *
- * $Log: copy.c,v $
- * Revision 1.32 1992/06/18 10:02:09 pab
- * corrected macros, etc
- *
- * Revision 1.31 1992/06/16 19:36:24 pab
- * weak wrapper code
- *
- * Revision 1.30 1992/06/14 16:43:45 pab
- * incorporated branch from V1.26
- *
- * Revision 1.29 1992/05/29 12:18:03 pab
- * changed headers
- *
- * Revision 1.28 1992/05/29 09:53:44 rjb
- * ALIGN8 and a NULL -> 0
- *
- * Revision 1.27 1992/05/29 09:47:44 djb
- * hooks for CGC mark+sweep (all #ifdef CGC)
- *
- * Revision 1.26 1992/04/30 19:41:21 pab
- * fiddled with tracing
- *
- * Revision 1.25 1992/04/30 11:07:31 pab
- * lost end-page bug. Lowered rounding
- *
- * Revision 1.24 1992/04/29 12:33:18 pab
- * tracing code added
- *
- * Revision 1.23 1992/04/27 21:55:42 pab
- * if it moves, round it
- *
- * Revision 1.22 1992/04/26 20:55:46 pab
- * fixes for generic version, plus static vector type preliminary support,
- * no-sockets fixes
- *
- * Revision 1.21 1992/03/13 18:06:51 pab
- * SysV fixes (mainly relinquishing pages and synchonisation)
- *
- * Revision 1.20 1992/02/27 15:46:57 pab
- * bytecode + error changes
- *
- * Revision 1.19 1992/02/13 13:49:58 pab
- * *** empty log message ***
- *
- * Revision 1.17 1992/02/11 13:38:04 pab
- * removed printing gc_enabled
- *
- * Revision 1.16 1992/02/10 12:11:41 pab
- * fixed circular lists
- * gc_enabaled now global
- *
- * revision 1.12 1991/04/02 21:25:30 kjp
- * compiler tidying.
- * copying garbage collector. Replaces allocate + garbage.c */
-
- #include "defs.h"
- #include "structs.h"
- #include "funcalls.h"
- #include "global.h"
- #include "state.h"
- #include "copy.h"
- #include "weak.h"
-
- #define N_SLOTS_IN_CLASS N_SLOTS_IN_STRUCT(struct class_structure)
- #define N_SLOTS_IN_THREAD N_SLOTS_IN_STRUCT(struct thread_structure)
-
- #define OTHER_SPACE(x) 1-(x)
-
- #define is_newspace(x) \
- ((gcof(x)&1) ==wspace)
-
- #define forwardof(x) \
- (lval_classof(x))
-
- #define set_forwarded(x, new) \
- ( *(&gcof(x))|=0x2 , forwardof(x)=new)
-
- #define is_forwarded(x) \
- ((gcof(x))&0x2)
-
- #define HEADERSIZE sizeof(Object_t)
- /* should not need to allocate any fixed objects yet... */
- #ifdef ALIGN8
- #define ROUNDTO 8
- #else
- #define ROUNDTO 4
- #endif
- #define ROUND_ADDR(x) ((((int)x)&(ROUNDTO-1))==0 ? x : x+(ROUNDTO-((int)x&(ROUNDTO-1))))
- #define is_fixed(x) 0
-
- #ifndef NODEBUG
- #define TRACE_GC /* writes allocation logging to a file */
- #endif
- #ifdef TRACE_GC
- #include <time.h>
- FILE *trace_file;
- int counters[256];
- int total_moved;
- #endif
-
- /* which space are we in */
- static int wspace;
- static char *free_ptr;
- static char *pg_end;
- int gc_paranoia=0;
- static int collect_count;
-
- /* BSD + SYSV */
- static LispObject GC_thread;
-
- /* SYSV only */
- SYSTEM_GLOBAL(SystemSemaphore,GC_sem);
- SYSTEM_GLOBAL(SystemSemaphore,Rig_sem);
- SYSTEM_GLOBAL(int,GC_state);
- static SYSTEM_GLOBAL(int,GC_register); /* Who's arrived so far... */
- static SYSTEM_GLOBAL(int,GC_exit_register); /* Who's left... */
- static SYSTEM_GLOBAL(int,GC_turn); /* whose go */
- static SYSTEM_GLOBAL(int,gc_enabled); /* can we... */
- static SYSTEM_GLOBAL_ARRAY1(LispObject,GC_register_array,MAX_PROCESSORS);
- static LispObject GC_tame_continue;
- static SYSTEM_GLOBAL(PageList, old_pages);
- /* Valid only in non-gc time */
- static SYSTEM_GLOBAL(PageList, free_pages);
- static SYSTEM_GLOBAL(int,npages);
- static SYSTEM_GLOBAL(int,pagelim);
-
- static SYSTEM_GLOBAL(LispObject, weak_list);
-
- static PageList current_page;
- static PageList used_pages;
-
- /* Called from inside copier */
- #define ALLOC_SPACE(new,type,ptr,size) \
- { \
- new= (type) ptr; \
- ptr+=size; \
- if (ptr>=pg_end) \
- { \
- GRAB_PAGE(NULL,ptr,pg_end); \
- new= (type) ptr; \
- ptr+=size; \
- } \
- }
-
- #ifdef MACHINE_ANY
- #define GRAB_PAGE_INTERNAL(stacktop,ptr,top) \
- { \
- ptr=free_pages->start; \
- top=free_pages->end; \
- current_page=free_pages; \
- free_pages=free_pages->next; \
- current_page->next=used_pages; \
- used_pages=current_page; \
- npages++; \
- COPY_BUG(fprintf(stderr,"{Grab: %d}", \
- current_page->id)); \
- }
-
- #define GRAB_PAGE(x,y,z) GRAB_PAGE_INTERNAL(x,y,z)
-
- #else
- #define GRAB_PAGE_INTERNAL(stacktop,ptr,top) \
- { \
- ptr=ROUND_ADDR(S_G_V(free_pages)->start); \
- top=S_G_V(free_pages)->end; \
- current_page=S_G_V(free_pages); \
- S_G_V(free_pages)=S_G_V(free_pages)->next; \
- current_page->next=used_pages; \
- used_pages=current_page; \
- S_G_V(npages)++; \
- COPY_BUG(fprintf(stderr,"{Grab(%d): %d}", \
- system_scheduler_number, \
- current_page->id)); \
- COPY_BUG(memset(ptr,'x',top-ptr)); \
- }
-
- #define GRAB_PAGE(stacktop,ptr,top) \
- { \
- system_open_semaphore(stacktop,&S_G_V(GC_sem)); \
- GRAB_PAGE_INTERNAL(stacktop,ptr,top); \
- system_close_semaphore(&S_G_V(GC_sem)); \
- }
-
- #endif
-
- #define MAYBE_GRAB_PAGE(res,stacktop,ptr,top) \
- { \
- system_open_semaphore(stacktop,&S_G_V(GC_sem)); \
- if (S_G_V(npages)<S_G_V(pagelim)) \
- { \
- GRAB_PAGE_INTERNAL(stacktop,ptr,top); \
- res=1; \
- } \
- else \
- res=0; \
- /**/ \
- system_close_semaphore(&S_G_V(GC_sem)); \
- }
-
- #define PRINT_LISTS(stream) \
- { \
- PageList xx; \
- fputs("Free: ",stream); \
- xx=S_G_V(free_pages); \
- while (xx!=NULL) \
- { fprintf(stream,"%d ",xx->id); \
- xx=xx->next; \
- } \
- fputs("\nUsed: ",stream); \
- xx=used_pages; \
- while (xx!=NULL) \
- { fprintf(stream,"%d ",xx->id); \
- xx=xx->next; \
- } \
- fputc('\n',stream); \
- }
-
-
- void init_allocator(int size)
- {
- #ifndef CGC
- PageList *newpage;
- char *space;
- char *end;
- int allocated=0;
- int pg_count=0;
-
- #ifndef MACHINE_ANY
-
- SYSTEM_INITIALISE_GLOBAL(SystemSemaphore,GC_sem,NULL);
- system_allocate_semaphore(&S_G_V(GC_sem));
- SYSTEM_INITIALISE_GLOBAL(SystemSemaphore,Rig_sem,NULL);
- system_allocate_semaphore(&S_G_V(Rig_sem));
- SYSTEM_INITIALISE_GLOBAL(int,GC_state,GC_DONE);
- SYSTEM_INITIALISE_GLOBAL(int,GC_register,0);
- SYSTEM_INITIALISE_GLOBAL(int,GC_exit_register,0);
- SYSTEM_INITIALISE_GLOBAL(int,pagelim,0);
- SYSTEM_INITIALISE_GLOBAL(PageList,free_pages,NULL);
- SYSTEM_INITIALISE_GLOBAL(PageList,old_pages,NULL);
- SYSTEM_INITIALISE_GLOBAL(int,npages,NULL);
- SYSTEM_INITIALISE_GLOBAL(int,GC_turn,NULL);
- SYSTEM_INITIALISE_GLOBAL_ARRAY1(LispObject,
- GC_register_array,MAX_PROCESSORS,NULL);
- #endif
-
- SYSTEM_INITIALISE_GLOBAL(int,gc_enabled,0);
- SYSTEM_INITIALISE_GLOBAL(LispObject,weak_list,NULL);
- newpage= &S_G_V(free_pages);
- #undef SYSTEM_MAX_SHARED_SIZE
- #define SYSTEM_MAX_SHARED_SIZE 512*1024
-
- while (allocated<size)
- {
- space=system_malloc(SYSTEM_MAX_SHARED_SIZE);
- end=space+SYSTEM_MAX_SHARED_SIZE;
- COPY_BUG(memset(space,'T',2*size));
-
- while (space<end)
- {
- *newpage=(PageList) space;
- (*newpage)->status=PAGE_FREE;
- (*newpage)->end= ((space+PAGE_SIZE) < end ? space+PAGE_SIZE : end);
- (*newpage)->id=pg_count;
- (*newpage)->next=NULL;
- newpage= &((*newpage)->next);
- space+=PAGE_SIZE;
- pg_count++;
- }
- allocated+=SYSTEM_MAX_SHARED_SIZE;
- }
-
- *newpage=NULL;
-
- printf("Initialised with: %x [%d pages]\n",size,pg_count);
- COPY_BUG(PRINT_LISTS(stderr));
- used_pages=NULL;
- wspace=0;
- S_G_V(pagelim)=pg_count/2;
- S_G_V(npages)=0;
- GRAB_PAGE(NULL,free_ptr,pg_end);
-
- #endif
- }
-
-
- void runtime_initialise_garbage_collector(LispObject *stacktop)
- {
- (GC_tame_continue)=allocate_continue(stacktop);
- GC_thread=nil;
-
- add_root(&GC_tame_continue);
- add_root(&GC_thread);
- }
-
- void initialise_garbage(LispObject *stacktop)
- { /* Pretend we're a module */
- LispObject garbage_collect(LispObject *);
-
- GC_thread = allocate_thread(stacktop,2048,1024,0);
- (void) make_module_function(stacktop,"GC",garbage_collect,0);
- }
-
- /* Called when a new process forks */
- #ifndef MACHINE_ANY
- void runtime_reset_allocator(LispObject *stacktop)
- {
- COPY_BUG(fprintf(stderr,"Proc: %d starting\n",system_scheduler_number));
-
- used_pages=NULL;
- GRAB_PAGE(NULL,free_ptr,pg_end);
-
- GC_thread = allocate_thread(stacktop,2048,1024,0);
- add_root(&GC_thread);
- (GC_tame_continue)=allocate_continue(stacktop);
- add_root(&GC_tame_continue);
- system_open_semaphore(stacktop,&S_G_V(Rig_sem));
- RIG_GC_THREAD(stacktop);
- system_close_semaphore(&S_G_V(Rig_sem));
-
- }
- #endif
-
- EUFUN_0(garbage_collect)
- {
- void do_gc_sync(LispObject *);
-
- do_gc_sync(stacktop);
- return nil;
-
- }
- EUFUN_CLOSE
-
- int current_space()
- {
- return wspace;
- }
-
- #ifndef MACHINE_ANY
- extern void rig_gc_thread(LispObject *stacktop)
- {
- #ifndef MACHINE_ANY
- RIG_GC_THREAD(stacktop);
- #endif
- }
- #endif
-
- /* c-roots */
- #define MAXROOTS 300
- static int nroots=0;
-
- LispObject *roots[MAXROOTS];
-
- int add_root(LispObject *root)
- {
- int x=nroots;
-
- roots[nroots++]=root;
-
- return x;
- }
-
- void copy_root(LispObject *x)
- {
- LispObject copy_object(LispObject);
- *x=copy_object(*x);
- }
-
- void copy_on()
- {
- S_G_V(gc_enabled)++;
- COPY_BUG(fprintf(stderr,"{+%d}",S_G_V(gc_enabled)));
- }
-
- void copy_off()
- {
- S_G_V(gc_enabled)--;
- COPY_BUG(fprintf(stderr,"{-%d}",S_G_V(gc_enabled)));
- }
-
- /* These will have to more complicated eventually */
- void ON_collect()
- {
- S_G_V(gc_enabled)++;
- COPY_BUG(fprintf(stderr,"{+%d}",S_G_V(gc_enabled)));
- }
-
- void OFF_collect()
- {
- S_G_V(gc_enabled)--;
- COPY_BUG(fprintf(stderr,"{-%d}",S_G_V(gc_enabled)));
- }
- /****************************************
- * allocation
- ****************************************/
-
- static int a_count;
- #define ALLOC_GAP 2048
- int alloc_gap=ALLOC_GAP;
-
- #ifdef CGC
- LispObject allocate_nbytes(LispObject *stacktop,int n,int type)
- {
- LispObject object;
-
- object=(LispObject)gc_malloc(n);
- lval_typeof(object)=type;
- return(object);
- }
- #else
- LispObject allocate_nbytes(LispObject *stacktop,int n,int type)
- {
- void do_gc_sync(LispObject *);
- LispObject object;
- char *new;
-
- COPY_BUG(if (n<HEADERSIZE) fprintf(stderr,"Object too small to hold header\n") );
-
- #ifdef TRACE_GC
- counters[type&255]++;
- #endif
-
- #ifndef NODEBUG
- if (gc_paranoia)
- fprintf(stdout,"{%x:%d}",type,n);
- #endif
- n=ROUND_ADDR(n);
- a_count+=n;
- #ifdef NODEBUG
- if ( !(free_ptr+n<pg_end))
- #else
- if ((gc_paranoia && a_count>alloc_gap && S_G_V(gc_enabled))
- || !(free_ptr+n<pg_end))
- #endif
- {
- int res;
- MAYBE_GRAB_PAGE(res,stacktop,free_ptr,pg_end);
-
- if (!res)
- {
- a_count=0;
- if (S_G_V(gc_enabled)<1)
- {
- fprintf(stderr,"{Grabbed Page 'cos I couldn't GC[%d]}\n",S_G_V(gc_enabled));
- GRAB_PAGE(stacktop,free_ptr,pg_end);
- }
- else
- {
- do_gc_sync(stacktop);
- }
- }
- }
- ALLOC_SPACE(object,LispObject,free_ptr,n);
-
- lval_typeof(object)=type;
- gcof(object)=(short)wspace;
- return(object);
- }
- #endif
-
- #ifdef MACHINE_ANY
- void do_gc_sync(LispObject *stacktop)
- {
- static void free_old_pgs(void);
- static void swap_spaces(LispObject *);
- static void free_weak_ptrs(void);
- fprintf(stderr,"Collection %d initiated: %d used, %d bytes (%d%%) remaining\n",
- collect_count,S_G_V(npages)*PAGE_SIZE,(S_G_V(pagelim)-S_G_V(npages))*PAGE_SIZE,0);
-
- S_G_V(old_pages)=NULL;
- S_G_V(npages)=0;
- S_G_V(weak_list)=NULL;
- swap_spaces(stacktop);
-
- free_old_pgs();
- free_weak_ptrs();
- }
- #else /* ! MACHINE_ANY */
- void do_gc_sync(LispObject *stacktop)
- {
- static void free_weak_ptrs(void);
- static void free_old_pgs(void);
- int i;
-
- /* we must save state early */
- save_state(stacktop,CURRENT_THREAD()->THREAD.state);
- /* Wait for the last gc to finish */
- while ( S_G_V(GC_state)!=GC_DONE
- &&S_G_V(GC_state)!=GC_SINKING)
- ;
- /* register myself */
- system_open_semaphore(stacktop,&S_G_V(GC_sem));
- ++S_G_V(GC_register);
- if (S_G_V(GC_register) == 1)
- { /* First */
- S_G_V(GC_state) = GC_SINKING;
- fprintf(stderr,"GC sinking(%d) --- ",S_G_V(gc_enabled));
- }
-
- fprintf(stderr,"%d ",system_scheduler_number);
- /* if last, set flag */
- if (S_G_V(GC_register) == RUNNING_PROCESSORS())
- { /* Last */
- S_G_V(GC_state) = GC_REGISTERED;
- fprintf(stderr,"\n"); fflush(stdout);
- fprintf(stderr,"Collection %d initiated: %d used, %d bytes (%d%%) remaining\n",
- collect_count,S_G_V(npages)*PAGE_SIZE,(S_G_V(pagelim)-S_G_V(npages))*PAGE_SIZE,0);
- S_G_V(GC_turn)=0;
- S_G_V(npages)=0;
- S_G_V(old_pages) = NULL;
- S_G_V(weak_list)=NULL;
- }
-
- system_close_semaphore(&S_G_V(GC_sem));
-
-
- SYSTEM_GLOBAL_ARRAY1_VALUE(GC_register_array,system_scheduler_number)
- = CURRENT_THREAD();
-
- /* boot any sleepers */
-
- system_kick_sleepers();
-
- /* wait until all get the idea */
- while (S_G_V(GC_state)!=GC_REGISTERED)
- ;
- /* Save myself */
-
- /* we all copy --- in serial 'cos its easier that way */
-
- while(S_G_V(GC_turn)!=system_scheduler_number)
- ;
-
- if (!set_continue(stacktop,(GC_tame_continue)))
- {
- LispObject temp = CURRENT_THREAD();
- LispObject *newstack;
-
- COPY_BUG(fprintf(stderr," {Proc: %d leaping %x %x %x}\n",system_scheduler_number,
- (GC_tame_continue)->CONTINUE.thread,GC_thread,temp));
- newstack = load_thread(GC_thread);
- call_continue(newstack,GC_thread->THREAD.state,temp);
- }
-
- /* done: should signal this */
-
- S_G_V(GC_turn)++;
-
- if (system_scheduler_number==RUNNING_PROCESSORS()-1)
- {
- free_old_pgs();
- free_weak_ptrs();
- S_G_V(GC_state)=GC_MARKED;
- }
-
- while(S_G_V(GC_state)!=GC_MARKED)
- ;
- /* Now we can go */
-
- system_open_semaphore(stacktop,&S_G_V(GC_sem));
- --S_G_V(GC_register);
- if (S_G_V(GC_register)==0)
- S_G_V(GC_state)=GC_DONE;
- system_close_semaphore(&S_G_V(GC_sem));
-
-
- fprintf(stderr,"GC done\n");
-
- }
-
-
- void first_gc_mark_call(LispObject *stacktop)
- {
- void swap_spaces(LispObject *stacktop);
-
- LispObject ret;
-
- COPY_BUG(printf("First invokation of GC mark: %x\n",stacktop); fflush(stdout));
- stacktop=GC_thread->THREAD.gc_stack_base;
- reset:
-
- ret = GC_thread->THREAD.state->CONTINUE.value;
-
- COPY_BUG(printf("Laying continue in GC mark: %x\n",stacktop); fflush(stdout));
- if (set_continue(stacktop,(GC_thread->THREAD.state)))
- {
- goto reset;
- }
- STACK_TMP(ret);
-
- COPY_BUG(printf("Marking in GC mark\n"); fflush(stdout));
-
- swap_spaces(stacktop);
- UNSTACK_TMP(ret);
- COPY_BUG(fprintf(stderr,"Jumping back: target: (%x %d) %x %d %d %d %d\n gc_thread: (%x %d) %x %d %d\n",
- ret,ret->THREAD.header.gc,
- ret->THREAD.state,
- ret->THREAD.state->CONTINUE.header.gc,
- ret->THREAD.state->CONTINUE.header.type,
- ret->THREAD.state->CONTINUE.handler_stack->CONS.header.type,
- ret->THREAD.state->CONTINUE.handler_stack->CONS.header.gc,
- GC_thread,
- GC_thread->THREAD.header.gc,
- GC_thread->THREAD.state,
- GC_thread->THREAD.state->CONTINUE.header.gc,
- GC_thread->THREAD.state->CONTINUE.header.type);
- fflush(stdout));
- /**save_state(stacktop,GC_thread);**/
- (void) load_thread(ret); /* this returns the wrong value for our porpoises */
- call_continue(NULL,(GC_tame_continue),nil);
- }
- #endif
-
-
-
- /* Collection */
-
- void swap_spaces(LispObject *stacktop)
- {
- void copy_root(LispObject *);
- void show_stack_space(void);
- static void free_old_pgs(void);
-
- char *oldspace;
- PageList pg,tmp,*ptr;
- int i;
-
- #ifdef TRACE_GC
- {
- long time_now;
- char *str;
- int k,j=0;
-
- if (trace_file==NULL)
- {
- char *buf[20];
- sprintf(buf,"/tmp/gc.%d",getpid());
-
- trace_file=fopen(buf,"w");
- }
-
- time_now=time(NULL);
- str=ctime(&time_now);
- fprintf(trace_file,"GC %d started: %s\n",collect_count,str);
- fprintf(trace_file,"Used: %d\n",S_G_V(npages)*PAGE_SIZE);
-
- for (k=0; k<255; k++)
- {
- if (counters[k]!=0)
- {
- fprintf(trace_file,"%d: %6d ",k,counters[k]);
- if ((++j)%6==0)
- fputc('\n',trace_file);
- }
- counters[k]=0;
- }
- total_moved=0;
- fputc('\n',trace_file);
- PRINT_LISTS(trace_file);
- fflush(trace_file);
- }
- #endif
-
- /* make sure that all is well */
- save_state(stacktop,CURRENT_THREAD()->THREAD.state);
- COPY_BUG(PRINT_LISTS(stderr));
-
- pg=current_page;
- used_pages=NULL;
- wspace=1-wspace;
- /* begin the copy process */
- GRAB_PAGE(stacktop,free_ptr,pg_end);
-
- for (i=0; i < nroots; i++)
- copy_root(roots[i]);
-
- /* Free all oldspace */
- /* Assumes that free_pages is unlocked */
- while (pg!=NULL)
- { /* insertion sort on the old pages */
- tmp=pg->next;
-
- ptr=&S_G_V(old_pages);
- if (*ptr!=NULL)
- {
- while ((*ptr)->next!=NULL
- && (*ptr)->next->id < pg->id)
- ptr=&(*ptr)->next;
-
- pg->next=(*ptr)->next;
- (*ptr)->next=pg;
- }
- else
- {
- *ptr=pg;
- pg->next=NULL;
- }
- pg=tmp;
- }
-
- fprintf(stderr,"Collection Completed: %d used, %d bytes (%d%%) remaining\n",
- S_G_V(npages)*PAGE_SIZE,
- (S_G_V(pagelim)-S_G_V(npages))*PAGE_SIZE,
- ((S_G_V(pagelim)-S_G_V(npages))*100)/
- S_G_V(pagelim));
- show_stack_space();
- collect_count++;
- COPY_BUG(PRINT_LISTS(stderr));
-
- #ifdef TRACE_GC
- {
- long time_now;
- char *str;
- int k,j;
- time_now=time(NULL);
- str=ctime(&time_now);
- fprintf(trace_file,"Using: %d\n",S_G_V(npages)*PAGE_SIZE);
- PRINT_LISTS(trace_file);
- fprintf(trace_file,"Totals: %d\n",total_moved);
- for (k=0,j=0; k<255; k++)
- {
- if (counters[k]!=0)
- {
- fprintf(trace_file,"%d: %6d ",k,counters[k]);
- if ((++j)%6==0)
- fputc('\n',trace_file);
- counters[k]=0;
- }
- }
- fprintf(trace_file,"GC %d complete: %s\n",collect_count,str);
- fflush(trace_file);
- }
- #endif
- return;
- }
-
- static void free_old_pgs()
- {
- PageList tmp;
-
- tmp=S_G_V(free_pages);
-
- if (tmp==NULL)
- S_G_V(free_pages)=S_G_V(old_pages);
- else
- {
- while(tmp->next!=NULL)
- {
- tmp=tmp->next;
- }
- tmp->next=S_G_V(old_pages);
- }
- }
-
- void free_weak_ptrs()
- {
- LispObject wptr;
-
- wptr=S_G_V(weak_list);
-
- while (wptr!=NULL)
- {
- if (is_forwarded(weak_ptr_val(wptr)))
- weak_ptr_val(wptr)=forwardof(weak_ptr_val(wptr));
- else
- weak_ptr_val(wptr)=nil;
-
- wptr=weak_ptr_chain(wptr);
- }
- S_G_V(weak_list)=NULL;
- }
- #ifndef NODEBUG
- #define CAREFUL_DECLS \
- LispObject copied;
-
- #ifdef NOLOWTAGINTS
- #define copy_obj_careful(x) \
- (copied=copy_object(x), \
- copied==NULL || ((gcof(copied)&1)==wspace) \
- ? copied \
- : (fprintf(stderr,"Wrong space\n"), system_lisp_exit(0), nil))
- #else
- #define copy_obj_careful(x) \
- (copied=copy_object(x), \
- (copied==NULL || is_fixnum(x) || ((gcof(copied)&1)==wspace)) \
- ? copied \
- : (fprintf(stderr,"Wrong space\n"), system_lisp_exit(0), nil))
-
- #endif /*NOLOWTAGINTS*/
- #else
- #define CAREFUL_DECLS
- #define copy_obj_careful(x) (copy_object(x))
- #endif
-
- #define FORWARD_HEADER(new,obj) \
- lval_typeof(new)=lval_typeof(obj); \
- gcof(new)=wspace; \
- class=lval_classof(obj); \
- set_forwarded(obj,new);
-
- #define COPY_ALLOC_SPACE(ptr,size) \
- ALLOC_SPACE(new,LispObject,ptr,ROUND_ADDR(size));
-
- /* Hack the stackpointer for GRAB_PAGE */
-
- LispObject copy_object(LispObject obj)
- {
- int i;
- LispObject new;
- LispObject class;
- CAREFUL_DECLS;
-
- if (obj==NULL) return NULL;
- #ifndef NOLOWTAGINTS
- if (is_fixnum(obj)) return obj;
- #endif
-
- if (is_forwarded(obj))
- return forwardof(obj);
-
- if (is_newspace(obj))
- return obj;
- else
- {
- #ifdef TRACE_GC
- counters[lval_typeof(obj)&255]++;
- #endif
-
- switch(lval_typeof(obj))
- {
- case TYPE_NULL:
- #if 0
- case TYPE_CONS:
- #endif
- /* Null is (cons nil nil) with hacked type */
- COPY_ALLOC_SPACE(free_ptr, sizeof(struct cons_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- CAR(new)=copy_obj_careful(CAR(obj));
- CDR(new)=copy_obj_careful(CDR(obj));
- break;
- #if 1
- case TYPE_CONS:
- /* allocate space */
- {
- LispObject walker,newcons;
- int count, max;
- COPY_ALLOC_SPACE(free_ptr, sizeof(struct cons_structure));
- FORWARD_HEADER(new,obj);
-
- CAR(new)=class;
- walker=CDR(obj);
- max=1;
- /* Note: this loop does not copy anything */
- while ( walker!=NULL
- #ifdef NOLOWTAGINTS
- && !is_fixnum(walker)
- #endif
- && is_cons(walker)
- && !is_forwarded(walker)
- && !is_newspace(walker))
- {
- ALLOC_SPACE(newcons,LispObject,free_ptr, sizeof(struct cons_structure));
- FORWARD_HEADER(newcons,walker);
- /* Keep the class safe */
- CAR(newcons)=class;
- walker=CDR(walker);
- max++;
- }
- /* COPY_BUG(fprintf(stderr,"(List: %d elts",max)); */
-
- newcons=new;
- /* This loop does all the copying
- end is now the stopping point */
-
- count=0;
- walker=obj;
- while (count<max)
- {
- lval_classof(newcons)=copy_obj_careful(CAR(newcons));
- CAR(newcons)=copy_obj_careful(CAR(walker));
- /* except for the end case equiv to CDR(newcons)=newcons+a bit */
- CDR(newcons)=copy_obj_careful(CDR(walker));
- walker=CDR(walker);
- newcons=CDR(newcons);
- count++;
- }
- }
- break;
- #endif
- #ifdef NOLOWTAGINTS
- case TYPE_INT:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct integer_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- intval(new)=intval(obj);
- break;
- #endif
- case TYPE_ENV:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct envobject));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->ENV.variable = copy_obj_careful(obj->ENV.variable);
- new->ENV.value = copy_obj_careful(obj->ENV.value);
- new->ENV.next = (Env) copy_obj_careful((LispObject)obj->ENV.next);
- new->ENV.mutable = copy_obj_careful(obj->ENV.mutable);
- break;
-
- case TYPE_B_MACRO:
- case TYPE_METHOD:
- case TYPE_GENERIC:
- case TYPE_B_FUNCTION:
- case TYPE_INSTANCE:
- /* allocate space */
- i=lval_classof(obj)->CLASS.local_count;
- COPY_ALLOC_SPACE(free_ptr, sizeof(Object_t)+ i*sizeof(LispObject));
- FORWARD_HEADER(new,obj);
-
- lval_classof(new)=copy_obj_careful(class);
- for (i=0 ; i<class->CLASS.local_count ; i++)
- slotref(new,i) = copy_obj_careful(slotref(obj,i));
- break;
-
- case TYPE_VECTOR:
- case TYPE_VECTOR|STATIC_TYPE:
- if (is_static(obj))
- {
- gcof(obj)=wspace; new=obj;
- class=lval_classof(obj);
- }
- else
- {
- COPY_ALLOC_SPACE(free_ptr,sizeof(Object_t)+sizeof(int)+sizeof(LispObject)*obj->VECTOR.length);
- FORWARD_HEADER(new,obj);
- }
- lval_classof(new)= copy_obj_careful(class);
- new->VECTOR.length=obj->VECTOR.length;
- for (i=0; i<obj->VECTOR.length; i++)
- vref(new,i) = copy_obj_careful(vref(obj,i));
- break;
-
- case TYPE_STRING:
- COPY_ALLOC_SPACE(free_ptr,ROUND_ADDR(sizeof(Object_t)+obj->STRING.length+sizeof(int)));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->STRING.length=obj->STRING.length;
- memcpy(stringof(new),stringof(obj),obj->STRING.length);
- break;
-
- case TYPE_CLASS:
- i=lval_classof(obj)->CLASS.local_count;
- COPY_ALLOC_SPACE(free_ptr, sizeof(Object_t)+ i*sizeof(LispObject));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- (new->CLASS).name = copy_obj_careful(obj->CLASS.name);
- (new->CLASS).superclasses = copy_obj_careful(obj->CLASS.superclasses);
- (new->CLASS).subclasses = copy_obj_careful(obj->CLASS.subclasses);
- (new->CLASS).slot_table = copy_obj_careful(obj->CLASS.slot_table);
- (new->CLASS).slot_list = copy_obj_careful(obj->CLASS.slot_list);
- (new->CLASS).direct_slot_list = copy_obj_careful(obj->CLASS.direct_slot_list);
- (new->CLASS).precedence = copy_obj_careful(obj->CLASS.precedence);
- (new->CLASS).local_count = obj->CLASS.local_count;
- for (i=N_SLOTS_IN_CLASS ; i<class->CLASS.local_count ; i++)
- slotref(new,i) = copy_obj_careful(slotref(obj,i));
- break;
-
- case TYPE_CHAR:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct character_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->CHAR.font=obj->CHAR.font;
- new->CHAR.code=obj->CHAR.code;
- break;
-
- case TYPE_TABLE:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct table_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->TABLE.comparator=obj->TABLE.comparator;
- new->TABLE.lisp_comparator= copy_obj_careful(obj->TABLE.lisp_comparator);
- new->TABLE.tree= copy_obj_careful(obj->TABLE.tree);
- break;
-
- case TYPE_CONTINUE:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct continue_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- (new->CONTINUE).thread = copy_obj_careful(obj->CONTINUE.thread);
-
- (new->CONTINUE).value = copy_obj_careful(obj->CONTINUE.value);
- (new->CONTINUE).target = copy_obj_careful((obj->CONTINUE).target);
-
- bcopy((char*)(obj->CONTINUE).machine_state,
- (char *)new->CONTINUE.machine_state,
- sizeof(new->CONTINUE.machine_state));
- (new->CONTINUE).gc_stack_pointer = obj->CONTINUE.gc_stack_pointer;
-
- (new->CONTINUE).dynamic_env = (Env)copy_obj_careful((LispObject)obj->CONTINUE.dynamic_env);
- (new->CONTINUE).last_continue = copy_obj_careful(obj->CONTINUE.last_continue);
- (new->CONTINUE).handler_stack = copy_obj_careful(obj->CONTINUE.handler_stack);
- (new->CONTINUE).dp = copy_obj_careful(obj->CONTINUE.dp);
-
- (new->CONTINUE).live = obj->CONTINUE.live;
- (new->CONTINUE).unwind = obj->CONTINUE.unwind;
- break;
-
- case TYPE_SPECIAL:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct special_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->SPECIAL.name = copy_obj_careful(obj->SPECIAL.name);
- new->SPECIAL.env = (Env)copy_obj_careful((LispObject)obj->SPECIAL.env);
- new->SPECIAL.func = obj->SPECIAL.func;
- break;
-
- case TYPE_SYMBOL:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct symbol_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- (new->SYMBOL).pname = copy_obj_careful(obj->SYMBOL.pname);
- (new->SYMBOL).lvalue = copy_obj_careful(obj->SYMBOL.lvalue);
- (new->SYMBOL).lmodule = copy_obj_careful(obj->SYMBOL.lmodule);
- (new->SYMBOL).gvalue = copy_obj_careful(obj->SYMBOL.gvalue);
- (new->SYMBOL).plist = copy_obj_careful(obj->SYMBOL.plist);
- (new->SYMBOL).left = copy_obj_careful(obj->SYMBOL.left);
- (new->SYMBOL).right = copy_obj_careful(obj->SYMBOL.right);
- (new->SYMBOL).hash = (obj->SYMBOL.hash);
- break;
-
- case TYPE_STREAM:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct stream_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new) = copy_obj_careful(class);
- (new->STREAM).handle = obj->STREAM.handle;
- (new->STREAM).name = copy_obj_careful(obj->STREAM.name);
- (new->STREAM).mode = obj->STREAM.mode;
- (new->STREAM).curchar = new->STREAM.curchar;
- break;
-
- case TYPE_C_MODULE: /* These are statically allocated, so just mark */
- /* forward to here -- unset fwd bit+ set right space */
- gcof(obj)=wspace; new=obj;
- class=lval_classof(obj);
- lval_classof(obj)=copy_obj_careful(class);
- obj->C_MODULE.name=copy_obj_careful(obj->C_MODULE.name);
- obj->C_MODULE.home=copy_obj_careful(obj->C_MODULE.home);
- obj->C_MODULE.imported_modules=copy_obj_careful(obj->C_MODULE.imported_modules);
- obj->C_MODULE.exported_names=copy_obj_careful(obj->C_MODULE.exported_names);
- obj->C_MODULE.bindings=copy_obj_careful(obj->C_MODULE.bindings);
- obj->C_MODULE.entry_count=copy_obj_careful(obj->C_MODULE.entry_count);
- obj->C_MODULE.values=copy_obj_careful(obj->C_MODULE.values);
-
- break;
-
- case TYPE_I_MODULE:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct i_module_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)= copy_obj_careful(class);
- new->I_MODULE.name= copy_obj_careful(obj->I_MODULE.name);
- new->I_MODULE.home= copy_obj_careful(obj->I_MODULE.home);
- new->I_MODULE.imported_modules= copy_obj_careful(obj->I_MODULE.imported_modules);
- new->I_MODULE.exported_names= copy_obj_careful(obj->I_MODULE.exported_names);
- new->I_MODULE.bindings= copy_obj_careful(obj->I_MODULE.bindings);
- new->I_MODULE.bounce_flag= obj->I_MODULE.bounce_flag;
- break;
-
- case TYPE_C_FUNCTION:
- case TYPE_C_MACRO:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct c_function_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new) = copy_obj_careful(class);
- new->C_FUNCTION.name = copy_obj_careful(obj->C_FUNCTION.name);
- new->C_FUNCTION.home = copy_obj_careful(obj->C_FUNCTION.home);
- new->C_FUNCTION.env = (Env)copy_obj_careful((LispObject)obj->C_FUNCTION.env);
- new->C_FUNCTION.argtype = obj->C_FUNCTION.argtype;
- new->C_FUNCTION.func=obj->C_FUNCTION.func;
- break;
-
- case TYPE_I_FUNCTION:
- case TYPE_I_MACRO:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct i_function_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->I_FUNCTION.name=copy_obj_careful(obj->I_FUNCTION.name);
- new->I_FUNCTION.home=copy_obj_careful(obj->I_FUNCTION.home);
- new->I_FUNCTION.env=(Env)copy_obj_careful((LispObject)obj->I_FUNCTION.env);
- new->I_FUNCTION.bvl=copy_obj_careful(obj->I_FUNCTION.bvl);
- new->I_FUNCTION.body=copy_obj_careful(obj->I_FUNCTION.body);
- new->I_FUNCTION.argtype=obj->I_FUNCTION.argtype;
- break;
-
- case TYPE_FLOAT:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct float_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- new->FLOAT.fvalue=obj->FLOAT.fvalue;
- break;
- #if (defined(WITH_BSD_SOCKETS) || defined(WITH_SYSTEMV_SOCKETS))
- case TYPE_LISTENER:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct listener_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- bcopy(&(obj->LISTENER.socket),&(new->LISTENER.socket),sizeof(new->LISTENER.socket));
- bcopy(&(obj->LISTENER.name),&(new->LISTENER.name),sizeof(new->LISTENER.name));
- bcopy(&(obj->LISTENER.state),&(new->LISTENER.state),sizeof(new->LISTENER.state));
- break;
-
- case TYPE_SOCKET:
- COPY_ALLOC_SPACE(free_ptr,sizeof(struct socket_structure));
- FORWARD_HEADER(new,obj);
- lval_classof(new)=copy_obj_careful(class);
- bcopy(&(obj->SOCKET.socket),&(new->SOCKET.socket),sizeof(new->SOCKET.socket));
- bcopy(&(obj->SOCKET.name),&(new->SOCKET.name),sizeof(new->SOCKET.name));
- bcopy(&(obj->SOCKET.state),&(new->SOCKET.state),sizeof(new->SOCKET.state));
- bcopy((obj->SOCKET.buffer),(new->SOCKET.buffer),sizeof(new->SOCKET.buffer));
- break;
- #endif
- case TYPE_THREAD:
- i=lval_classof(obj)->CLASS.local_count;
- COPY_ALLOC_SPACE(free_ptr, sizeof(Object_t)+ i*sizeof(LispObject));
- FORWARD_HEADER(new,obj);
- lval_classof(new) = copy_obj_careful(class);
- new->THREAD.stack_size = obj->THREAD.stack_size;
- new->THREAD.gc_stack_size = obj->THREAD.gc_stack_size;
-
- new->THREAD.fun = copy_obj_careful(obj->THREAD.fun);
- new->THREAD.args = copy_obj_careful(obj->THREAD.args);
- new->THREAD.value = copy_obj_careful(obj->THREAD.value);
-
- new->THREAD.status = obj->THREAD.status;
-
- new->THREAD.parent = copy_obj_careful(obj->THREAD.parent);
- new->THREAD.cochain = copy_obj_careful(obj->THREAD.cochain);
-
- new->THREAD.state = copy_obj_careful(obj->THREAD.state);
-
- new->THREAD.stack_base = obj->THREAD.stack_base;
- new->THREAD.gc_stack_base = obj->THREAD.gc_stack_base;
- for (i=N_SLOTS_IN_THREAD ; i<class->CLASS.local_count ; i++)
- slotref(new,i) = copy_obj_careful(slotref(obj,i));
- /* hack */
- if (obj->THREAD.gc_stack_base+obj->THREAD.gc_stack_size < obj->THREAD.state->CONTINUE.gc_stack_pointer)
- fprintf(stderr,"GC Stack overflow detected\n");
-
- {
- LispObject *x=obj->THREAD.gc_stack_base;
-
- while (x<obj->THREAD.state->CONTINUE.gc_stack_pointer)
- {
- if (!(((int) *x)&1)) /* Check for tags here */
- *x = copy_obj_careful(*x);
- ++x;
- }
- }
- break;
-
- case TYPE_WEAK_WRAPPER:
- COPY_ALLOC_SPACE(free_ptr,WEAK_PTR_SIZE*sizeof(LispObject)+sizeof(Object_t));
- FORWARD_HEADER(new,obj);
- lval_classof(new) = copy_obj_careful(class);
- weak_ptr_chain(new)=S_G_V(weak_list);
- weak_ptr_val(new)=weak_ptr_val(obj);
- S_G_V(weak_list)=new;
- break;
-
- default:
- fprintf(stderr,"Can't copy: %x\n",typeof(obj));
- return obj;
- break;
- }
- return new;
- }
- }
-
- /*****************************************/
- /* Old code */
-
- #ifdef NOWAY /* Attempt to allocate n objects --- not really viable */
- static char * allocate_bytes(LispObject *stacktop,int n);
- LispObject allocate_nbytes(LispObject *stacktop, int size, int type)
- {
- LispObject object;
-
- object=(LispObject) allocate_bytes(stacktop,size);
-
- lval_typeof(object)=type;
- gcof(object)=(short)wspace;
- return(object);
- }
-
- LispObject allocate_cbytes(LispObject *stacktop, int n, int size, int type)
- {
- char *space,*ptr;
- int i;
-
- /* Hope to get lucky of alignment */
- space= allocate_bytes(stacktop,size*n);
- ptr=space;
-
- for (i=0; i<n; i++)
- {
- LispObject new;
- new=(LispObject)ptr;
- lval_typeof(new)=type;
- gcof(new)=wspace;
-
- ptr+=size;
- }
- return (LispObject) space;
- }
- #endif
-
-