/************************************************************************* * * * BEAM -> Basic Extended Andorra Model * * BEAM extends the YAP Prolog system to support the EAM * * * * Copyright: Ricardo Lopes and NCC - University of Porto, Portugal * * * ************************************************************************** * comments: garbage collector routines * *************************************************************************/ void garbage_collector(void); struct OR_BOX *move_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call); struct AND_BOX *move_andbox(struct AND_BOX *a,struct OR_BOX *parent,struct status_or *alt); Cell refresh_structures(Cell c); Cell move_structures(Cell c); void refresh_andbox(struct AND_BOX *a); void refresh_orbox(struct OR_BOX *o); Cell refresh_structures(Cell c) { Cell *C, OldC; OldC=deref((Cell) c); if (isvar(OldC)) { return(OldC); } if (isatom(OldC)) { return(OldC); } if (isappl(OldC)) { int i,arity; C=(Cell *) repappl(OldC); arity = ((int) ArityOfFunctor((Functor) *C)); for(i=0;i=beam_START_ADDR_HEAP+beam_MEM_H/2 && ((unsigned long) OldC) =(Cell *) beam_START_ADDR_BOXES) beam_NextFree=beam_H+1; else beam_NextFree=(Cell *) beam_START_ADDR_BOXES; beam_H=(Cell *) beam_START_ADDR_HEAP; beam_MemGoing=1; beam_sp=(Cell *) beam_END_H; beam_sp-=2; } beam_Mem_FULL=0; beam_su=NULL; new_top=move_andbox(beam_top,NULL,NULL); beam_top=new_top; #if Clear_MEMORY if (beam_MemGoing==-1) { memset((void *) beam_START_ADDR_HEAP,0,MEM_H/2); memset((void *) beam_START_ADDR_BOXES,0,MEM_BOXES/2); } else { memset((void *) beam_START_ADDR_HEAP+MEM_H/2,0,MEM_H/2); memset((void *) beam_START_ADDR_BOXES+MEM_BOXES/2,0,MEM_BOXES/2); } #endif #endif #if Memory_Stat if (beam_MemGoing==1) { beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][3]=(unsigned long) beam_H- beam_START_ADDR_HEAP; beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][4]=(unsigned long) beam_NextFree- beam_START_ADDR_BOXES; } else { beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][3]=(unsigned long) beam_H- beam_START_ADDR_HEAP-MEM_H/2; beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][4]= beam_END_BOX- ((unsigned long) beam_NextFree); } if (GARBAGE_COLLECTOR==1) beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][4]= beam_END_BOX- ((unsigned long) beam_NextFree); #endif #if Debug_Dump_State & 2 dump_eam_state(); #endif #if Debug printf("End of Garbage Collector\n"); #endif } #if GARBAGE_COLLECTOR!=1 struct OR_BOX *move_orbox(struct OR_BOX *o,struct AND_BOX *parent,struct status_and *nr_call) { struct OR_BOX *new_orbox; struct status_or *old, *new, *first=NULL, *last=NULL; Cell *args,*newargs; if (o==NULL) return(NULL); #if !Fast_go if ((Cell *) o<(Cell *) beam_START_ADDR_BOXES || (Cell *) o>(Cell *) beam_END_BOX) return (NULL); #endif new_orbox=(struct OR_BOX *) request_memory(ORBOX_SIZE); if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n"); if (beam_OBX==o) beam_OBX=new_orbox; new_orbox->parent=parent; new_orbox->nr_call=nr_call; new_orbox->nr_all_alternatives=o->nr_all_alternatives; old=o->alternatives; while(old!=NULL) { new=(struct status_or *) request_memory(STATUS_OR_SIZE); if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n"); if (beam_nr_alternative==old) beam_nr_alternative=new; new->args=old->args; new->code=old->code; new->state=old->state; new->alternative=move_andbox(old->alternative,new_orbox,new); if (first==NULL) first=new; else last->next=new; new->previous=last; new->next=NULL; last=new; old=old->next; } new_orbox->alternatives=first; args=NULL; newargs=NULL; while(last!=NULL) { if (last->args==NULL) { args=NULL; newargs=NULL; } else if (args!=last->args) { int y; args=last->args; #if Debug printf("Request args=%d \n",(int) args[0]); #endif newargs=(Cell *)request_memory((args[0])*sizeof(Cell)); if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n"); newargs[0]=args[0]; for(y=1;yargs=newargs; last=last->previous; } return(new_orbox); } struct AND_BOX *move_andbox(struct AND_BOX *a,struct OR_BOX *parent, struct status_or *alt ) { int OLD_VAR_TRAIL_NR; struct AND_BOX *new_andbox; struct PERM_VAR *l; struct EXTERNAL_VAR *old_externals,*externals; if (a==NULL) return(NULL); OLD_VAR_TRAIL_NR=beam_VAR_TRAIL_NR; new_andbox=(struct AND_BOX *) request_memory(ANDBOX_SIZE); if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n"); if (beam_ABX==a) beam_ABX=new_andbox; new_andbox->parent=parent; new_andbox->nr_alternative=alt; new_andbox->level=a->level; new_andbox->side_effects=a->side_effects; new_andbox->suspended=NULL; if (a->suspended) { new_andbox->suspended=addto_suspensions_list(new_andbox,a->suspended->reason); } new_andbox->perms=a->perms; l=a->perms; while(l!=NULL) { /* ainda nao estou a fazer GC nas Var Perm */ l->value=move_structures(l->value); l->home=new_andbox; l->suspensions=NULL; l=l->next; } old_externals=a->externals; externals=NULL; while(old_externals) { struct EXTERNAL_VAR *e; struct SUSPENSIONS_VAR *s; e=(struct EXTERNAL_VAR *) request_memory(EXTERNAL_VAR_SIZE); e->next=externals; externals=e; e->value=move_structures(old_externals->value); e->var=(struct PERM_VAR *) old_externals->var; //e->var=(struct PERM_VAR *) old_externals->var; CUIDADO QUANDO FIZER GC PERM_VARS if (isvar(e->var)) { s=(struct SUSPENSIONS_VAR *) request_memory(SUSPENSIONS_VAR_SIZE); s->and_box=new_andbox; s->next=e->var->suspensions; e->var->suspensions=s; } old_externals=old_externals->next; } new_andbox->externals=externals; if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n"); /* CUIDADO: Preciso agora de duplicar os vectores das variaveis locais */ { struct status_and *calls; #if !Fast_go Cell **backup=NULL; int i, counted=0,max=1000; backup=(Cell **) malloc(max); #else Cell *backup[1000]; int i, counted=0; #endif calls=a->calls; while(calls!=NULL) { if (calls->locals!=NULL) { /* primeiro vou ver se já foi copiado */ for(i=0;ilocals) { calls->locals=backup[i+1]; break; } } if (i==counted) { /* afinal ainda nao foi copiado: fazer copia em duas fases*/ Cell *c, *newvars, *oldvars; int nr; oldvars=calls->locals; nr=oldvars[-1]; newvars=request_memory_locals(nr); if (beam_varlocals==oldvars) beam_varlocals=newvars; calls->locals=newvars; /* primeiro actualizo as variaveis */ for(i=0;i=998) abort_eam("No more memory... realloc in gc \n"); #endif backup[counted]=oldvars; backup[counted+1]=newvars; counted+=2; } } calls=calls->next; } #if !Fast_go free(backup); #endif } new_andbox->nr_all_calls=a->nr_all_calls; { struct status_and *first=NULL, *last=NULL,*calls,*calls_new; calls=a->calls; while(calls!=NULL){ calls_new=(struct status_and *) request_memory(STATUS_AND_SIZE); if (beam_Mem_FULL) abort_eam("Sem Memoria para GC\n"); calls_new->code=calls->code; calls_new->state=calls->state; calls_new->locals=calls->locals; if (beam_nr_call==calls) beam_nr_call=calls_new; calls_new->call=move_orbox(calls->call,new_andbox,calls_new); if (first==NULL) first=calls_new; else last->next=calls_new; calls_new->previous=last; calls_new->next=NULL; last=calls_new; calls=calls->next; } new_andbox->calls=first; } return(new_andbox); } #else /* used by GC Only on Heap || Keep boxes on same memory */ void refresh_orbox(struct OR_BOX *o) { struct status_or *old, *last=NULL; Cell *args; if (o==NULL) return; old=o->alternatives; while(old!=NULL) { refresh_andbox(old->alternative); last=old; old=old->next; } args=NULL; while(last!=NULL) { if (last->args==NULL) { args=NULL; }else if (args!=last->args) { int y; args=last->args; for(y=1;yprevious; } return; } void refresh_andbox(struct AND_BOX *a) { struct PERM_VAR *l; struct EXTERNAL_VAR *externals; struct status_and *calls; if (a==NULL) return; l=a->perms; while(l!=NULL) { l->value=move_structures(l->value); l=l->next; } externals=a->externals; while(externals) { externals->value=move_structures(externals->value); externals=externals->next; } calls=a->calls; while(calls!=NULL) { // if (calls->calls!=NULL) { if (calls->locals!=NULL && ((int) calls->locals[-1]>0) { int nr,i; nr=calls->locals[-1]; calls->locals[-1]=-nr; for(i=0;ilocals[i]=move_structures(calls->locals[i]); } } refresh_orbox(calls->call); // } calls=calls->next; } calls=a->calls; while(calls!=NULL) { if (calls->locals!=NULL && ((int) calls->locals[-1])<0) { int nr; nr=calls->locals[-1]; calls->locals[-1]=-nr; } calls=calls->next; } return; } #endif