This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/BEAM/eam_gc.c
2009-02-16 12:33:37 +00:00

499 lines
13 KiB
C
Raw Blame History

/*************************************************************************
* *
* 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<arity ;i++) {
C++;
*C=refresh_structures((Cell) C);
}
return(OldC);
}
/* else if (ispair(c)) { */
C=(Cell *) reppair(OldC);
*C=refresh_structures((Cell) C);
C++;
*C=refresh_structures((Cell) C);
return(OldC);
}
Cell move_structures(Cell c)
{
Cell *NewC, *NewH;
Cell OldC,OldH;
OldC=deref((Cell) c);
/*
if (beam_MemGoing==1 && ((unsigned long) OldC) <beam_START_ADDR_HEAP+beam_MEM_H/2) return(OldC);
if (beam_MemGoing==-1 && ((unsigned long) OldC)>=beam_START_ADDR_HEAP+beam_MEM_H/2 && ((unsigned long) OldC) <beam_START_ADDR_BOXES) return(OldC);
*/
if (isvar(OldC)) {
return(OldC);
}
if (isatom(OldC)) {
return(OldC);
}
OldH=(Cell) beam_H;
NewH=beam_H;
if (isappl(OldC)) {
int i,arity;
NewC=(Cell *) repappl(OldC);
arity = ((int) ArityOfFunctor((Functor) *NewC));
*NewH++=*NewC++;
beam_H+=arity+1;
for(i=0;i<arity ;i++) {
*NewH=move_structures((Cell) NewC);
NewH++;
NewC++;
}
return(absappl(OldH));
}
/* else if (ispair(c)) { */
NewC=(Cell *) reppair(OldC);
beam_H+=2;
*NewH=move_structures((Cell) NewC);
NewC++;
NewH++;
*NewH=move_structures((Cell) NewC);
return(abspair(OldH));
}
void garbage_collector()
{
#if GARBAGE_COLLECTOR==2
struct AND_BOX *new_top;
#endif
if (beam_Mem_FULL & 2) beam_nr_gc_heap++; else beam_nr_gc_boxed++;
#if Debug || Debug_GC
printf("Entering Garbage Collector for the %dth time (Reason=%d)\n",beam_nr_gc_heap+beam_nr_gc_boxed,beam_Mem_FULL);
#endif
#if Debug_Dump_State & 2
dump_eam_state();
printf("--------------------------------------------------------------------\n");
#endif
beam_Mem_FULL=0;
#if Memory_Stat
if (beam_MemGoing==1) {
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][1]=(unsigned long) beam_H-beam_START_ADDR_HEAP;
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][2]=(unsigned long) beam_NextFree-beam_START_ADDR_BOXES;
} else {
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][1]=(unsigned long) beam_H-beam_START_ADDR_HEAP-MEM_H/2;
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][2]=beam_END_BOX- ((unsigned long) beam_NextFree);
}
if (GARBAGE_COLLECTOR==1)
beam_Memory_STAT[beam_nr_gc_heap+beam_nr_gc_boxed][2]=beam_END_BOX- ((unsigned long) beam_NextFree);
#endif
#if GARBAGE_COLLECTOR==1
if (beam_MemGoing==1) {
if (beam_H < (Cell *) (beam_START_ADDR_HEAP+MEM_H/2)) beam_H=(Cell *) (beam_START_ADDR_HEAP+MEM_H/2); else beam_H++;
beam_MemGoing=-1;
beam_sp=(Cell *) beam_START_ADDR_HEAP+MEM_H/2;
beam_sp--;
} else {
beam_H=(Cell *) beam_START_ADDR_HEAP;
beam_MemGoing=1;
beam_sp=(Cell *) beam_END_H;
beam_sp--;
}
refresh_andbox(beam_top);
#if Clear_MEMORY
if (beam_MemGoing==-1) {
memset(beam_START_ADDR_HEAP,0,MEM_H/2);
} else {
memset(beam_START_ADDR_HEAP+MEM_H/2,0,MEM_H/2);
}
#endif
#else
memset(beam_IndexFree,0,INDEX_SIZE*POINTER_SIZE);
if (beam_MemGoing==1) {
if (beam_H < (Cell *) (beam_START_ADDR_HEAP+MEM_H/2)) beam_H=(Cell *) (beam_START_ADDR_HEAP+MEM_H/2); else beam_H++;
beam_NextFree=(Cell *) beam_END_BOX;
beam_MemGoing=-1;
beam_sp=(Cell *) beam_START_ADDR_HEAP+MEM_H/2; beam_sp-=2;
} else {
if (beam_H>=(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;y<args[0];y++) newargs[y]=move_structures(args[y]);
}
last->args=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;i<counted;i+=2) {
if (backup[i]==calls->locals) {
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<nr;i++) {
c=&oldvars[i];
if ((Cell *)*c==c) {
newvars[i]=(Cell) &newvars[i];
*c=newvars[i];
} else {
newvars[i]= (Cell) *c;
*c=(Cell) &newvars[i];
}
}
/* depois copio as estruturas */
for(i=0;i<nr;i++) {
newvars[i]=move_structures(oldvars[i]);
}
#if !Fast_go
if (max<counted+2) {
max+=200;
backup=realloc(backup,max);
if (backup==NULL) abort_eam("No more memory... realloc in gc \n");
}
#else
if (counted>=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;y<args[0];y++) {
args[y]=move_structures(args[y]);
}
}
last=last->previous;
}
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;i<nr;i++) {
calls->locals[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