C:/Users/Dennis/src/lang/Life_start/Life/life-1.02/source/memory.c

Go to the documentation of this file.
00001 /* Copyright 1991 Digital Equipment Corporation.
00002 ** All Rights Reserved.
00003 *****************************************************************/
00004 /*      $Id: memory.c,v 1.10 1995/07/27 19:03:24 duchier Exp $   */
00005 
00006 #ifndef lint
00007 static char vcid[] = "$Id: memory.c,v 1.10 1995/07/27 19:03:24 duchier Exp $";
00008 #endif /* lint */
00009 
00010 /* need stdlib.h to declare atof */
00011 #include <stdlib.h>
00012 #include "extern.h"
00013 #include "print.h"
00014 #include "login.h"
00015 #include "lefun.h"
00016 #include "token.h"
00017 #include "error.h"
00018 #include "xpred.h"
00019 #include "modules.h" /*  RM: Jan 13 1993  */
00020 /* #include <malloc.h> 11.9 */
00021 
00022 /* external variables */
00023 
00024 GENERIC mem_base;
00025 GENERIC mem_limit;
00026 GENERIC stack_pointer;
00027 GENERIC heap_pointer;
00028 GENERIC other_base;
00029 
00030 GENERIC other_limit;
00031 GENERIC other_pointer;
00032 
00033 static long delta;
00034 
00035 #ifdef prlDEBUG
00036 static long amount_used;
00037 #endif
00038 
00039 #ifdef CLIFE
00040 long pass;
00041 #else 
00042 static long pass;
00043 #endif /* CLIFE */
00044 
00045 #define LONELY 1
00046 
00047 #ifndef OS2_PORT
00048 static struct tms last_garbage_time;
00049 #else
00050 static float last_garbage_time;
00051 #endif
00052 static float gc_time, life_time;
00053 
00054 
00055 int mem_size;
00056 int alloc_words;
00057 
00058 #define ALIGNUP(X) { (X) = (GENERIC)( ((long) (X) + (ALIGN-1)) & ~(ALIGN-1) ); }
00059 
00060 
00061 
00062 /************* STUFF FOR PARSING COMMAND LINE ARGS ************************/
00063 
00064 char *GetStrOption(name,def)
00065 char *name;
00066 char *def;
00067 {
00068   int i;
00069   char *result=def;
00070   int l=strlen(name);
00071   
00072   for(i=1;i<arg_c;i++)
00073     if(arg_v[i][0]=='-' && (int)strlen(arg_v[i])>=l+1)
00074       if(!strncmp(arg_v[i]+1,name,l))
00075         if(arg_v[i][l+1]=='=')
00076           result=arg_v[i]+l+2;
00077         else
00078           result=arg_v[i]+l+1;  
00079   
00080   return result;
00081 }
00082 
00083 
00084 
00085 int GetBoolOption(name)
00086 char *name;
00087 {
00088   char *s;
00089   s=GetStrOption(name,"off");
00090   return strcmp(s,"off");
00091 }
00092 
00093 
00094 
00095 int GetIntOption(name,def)
00096 char *name;
00097 int def;
00098 {
00099   char *s;
00100   char buffer[40];
00101   sprintf(buffer,"%d",def);
00102   s=GetStrOption(name,buffer);
00103   return atof(s);
00104 }
00105 
00106 /****************************************************************************/
00107 
00108 
00109 
00110 
00111 
00112 void pchoices() /*  RM: Oct 28 1993  For debugging. */
00113 {
00114   ptr_choice_point c;
00115   printf("stack pointer is: %x\n",stack_pointer);
00116   for(c=choice_stack;c;c=c->next)
00117     printf("\tc=%x\ts=%x\tg=%x\tu=%x\n",c,c->stack_top,c->goal_stack,c->undo_point);
00118 }
00119 
00120 
00121 
00122 
00123 /****************************************************************************/
00124 
00125 /* GC sanity checks */
00126 
00127 /* Keep for release versions, unless the garbage collector is very robust */
00128 /* #define GCTEST */
00129 
00130 /* Remove for release versions */
00131 /* #define GCVERBOSE */
00132 
00133 #ifndef GCTEST
00134 #undef assert
00135 #define assert(N)
00136 #endif
00137 
00138 void print_undo_stack()
00139 {
00140   ptr_stack u=undo_stack;
00141 
00142   while (u) {
00143     if (u->a<mem_base || u->a>mem_limit ||
00144         (GENERIC)u->next<mem_base || (GENERIC)u->next>mem_limit) {
00145       printf("UNDO: type:%ld a:%lx b:%lx next:%lx\n",u->type,u->a,u->b,u->next);
00146       fflush(stdout);
00147     }
00148     u=u->next;
00149   }
00150 }
00151 
00152 long bounds_undo_stack()
00153 /* Address field in undo_stack is within range */
00154 /* The only valid address outside this range is that of xevent_state */
00155 {
00156   ptr_stack u=undo_stack;
00157 
00158   while (u) {
00159     if (  (GENERIC)u<mem_base
00160        || (GENERIC)u>mem_limit
00161        || (!VALID_ADDRESS(u->a) && !(u->type & undo_action))
00162        ) {
00163       if ((GENERIC)u<mem_base || (GENERIC)u>mem_limit) {
00164         printf("\nUNDO: u=%lx\n",(long)u);
00165       }
00166       else {
00167         printf("\nUNDO: u:%lx type:%ld a:%lx b:%lx next:%lx\n",
00168                (long)u,u->type,u->a,u->b,u->next);
00169       }
00170       fflush(stdout);
00171       return FALSE;
00172     }
00173     u=u->next;
00174   }
00175 
00176   return TRUE;
00177 }
00178 
00179 
00180 /****************************************************************************/
00181 
00182 /* Forward declarations */
00183 static void check_psi_list();
00184 static void check_resid_list(); /* 21.9 */
00185 static void check_choice();
00186 static void check_undo_stack();
00187 
00188 
00189 
00190 
00191 /******** FAIL_ALL()
00192   This routines provokes a total failure, in case of a bad error
00193   (out of memory, abort, etc...).
00194   All goals are abandoned.
00195 */
00196 void fail_all()
00197 {
00198   output_stream=stdout;         
00199   choice_stack=NULL;
00200   goal_stack=NULL;
00201   undo_stack=NULL;
00202   abort_life(TRUE);
00203   /* printf("\n*** Abort\n"); */
00204   stdin_cleareof();
00205   open_input_file("stdin");
00206 }
00207 
00208 
00209 
00210 
00211 /******************************************************************************
00212 
00213   GARBAGE COLLECTING.
00214 
00215 */
00216 
00217 
00218 
00219 void check_attr();
00220 void check_psi_term();
00221 void check_definition();
00222 void check_resid_block();
00223 
00224 
00225 /*  RM: Jan 29 1993  Replaced with PVR's version of 26.1 */
00226 
00227 /******** COMPRESS()
00228   This routine compresses the memory contents and
00229   calculates the new addresses. First the Stack is compressed, bottom up.
00230   Secondly the Heap is compressed, top down.
00231 */
00232 static void compress()
00233 {
00234     GENERIC addr, new_addr;
00235     long len, i;
00236   
00237     /* Compressing the stack: */
00238   
00239     addr=new_addr=mem_base;
00240     while (addr<=stack_pointer) {
00241       len = *(addr+delta);
00242       if (len) {
00243         /* There are lots of these: */
00244         /* if (len==LONELY) printf("Isolated LONELY at %lx\n",addr); */
00245         if (len==LONELY) len=ALIGN;
00246         else if (len & (ALIGN-1)) len=len-(len & (ALIGN-1))+ALIGN;
00247         /* if (len & (ALIGN-1)) len=len-(len & (ALIGN-1))+ALIGN; 12.6 */
00248         assert((len & (ALIGN-1))==0);
00249         len /= sizeof(*addr);
00250         assert(len>0);
00251   
00252         for (i=0; i<len; i++) {
00253           *new_addr = *addr;
00254           if (i>0) {
00255             if (*(addr+delta)>=len)
00256               assert(i>0 ? *(addr+delta)<len : TRUE);
00257           }
00258           assert(VALID_ADDRESS(new_addr));
00259           *(addr+delta) = (long)new_addr + 1; /* Set low bit */
00260 #ifdef prlDEBUG
00261           if (*(addr+delta) & 1 == 0)
00262             printf ("compress: could be a bug ...\n");
00263 #endif
00264           addr++;
00265           new_addr++;
00266         }
00267       }
00268       else
00269         addr++;
00270     }
00271     other_pointer=stack_pointer; /* 10.6 this var. is unused */
00272     stack_pointer=new_addr;
00273   
00274     /* Compressing the heap: */
00275   
00276     addr=new_addr=mem_limit;
00277     addr--;  /* PVR fix: adding this statement avoids accessing beyond */
00278              /* the memory's edge, which causes a segmentation fault on*/
00279              /* SPARC. */
00280     while (addr>=heap_pointer) {
00281     skip_addr:
00282       len= *(addr+delta);
00283       if (len) {
00284         if (len!=LONELY) {
00285 
00286           if (len & (ALIGN-1)) len=len-(len & (ALIGN-1))+ALIGN;
00287           assert((len & (ALIGN-1))==0);
00288           len /= sizeof (*addr);
00289           assert(len>0);
00290 
00291         } else { /* len==LONELY */
00292           GENERIC a;
00293 
00294           if (len & (ALIGN-1)) len=len-(len & (ALIGN-1))+ALIGN;
00295           assert((len & (ALIGN-1))==0);
00296           len /= sizeof (*addr);
00297           assert(len==1);
00298 
00299           /* Check if the LONELY field is actually part of a block. */
00300           /* If so, skip to the beginning of the block. */
00301           a=addr;
00302           do {
00303             a--;
00304           } while (a>=heap_pointer &&
00305                    (*(a+delta)==0 || *(a+delta)==LONELY));
00306           if (a>=heap_pointer && *(a+delta)/sizeof(*a)+a>addr) {
00307             addr=a;
00308             goto skip_addr;
00309           }
00310         }
00311 
00312         /* Move a block or an isolated LONELY field. */
00313         addr += len;
00314         for (i=0; i<len; i++) {
00315           addr--;
00316           new_addr--;
00317           *new_addr = *addr;
00318           assert(VALID_ADDRESS(new_addr));
00319           *(addr+delta) = (long)new_addr + 1;
00320         }
00321       }
00322       addr--;
00323     }
00324     heap_pointer=new_addr;
00325 }
00326 
00327 
00328 
00329 #define UNCHECKED(P) (! *((GENERIC)(P)+delta))
00330 
00331 /******** UNCHECKED(p,l)
00332   P is a pointer to a structure L bytes in length.
00333   If L=LONELY then that means that P is a pointer to a sub-field of a
00334   structure.
00335   The function returns TRUE if the structure has not been yet thoroughly
00336   explored, otherwise FALSE.
00337   If this is the second pass then it translates P to its new value
00338   (as calculated by COMPRESS).
00339 */
00340 
00341 
00342 
00343 #ifdef CLIFE
00344 long unchecked (p, len)
00345 #else
00346 static long unchecked (p, len)
00347 #endif /* CLIFE */
00348 GENERIC *p; 
00349 long len;
00350 {
00351   GENERIC addr;
00352   long result=FALSE, value;
00353 
00354   assert(len>0);
00355   if ((unsigned long)*p>MAX_BUILT_INS) {
00356 #ifdef GCTEST
00357     if (!VALID_ADDRESS(*p)) {
00358       printf("p=%lx,*p=%lx\n",p,*p);
00359     }
00360 #endif
00361     assert(VALID_ADDRESS(*p));
00362     addr = *p + delta;
00363     value = *addr;
00364     switch (pass) {
00365     case 1:
00366 #ifdef GCTEST
00367       if (FALSE /* len>100 || value>100 13.8 */) {
00368         /* This does in fact happen */
00369         printf("len=%ld,value=%ld\n",len,value);
00370         fflush(stdout);
00371       }
00372 #endif
00373       /* if (!value) */
00374       if (!value || value==LONELY) {
00375         /* Pointer not yet explored */
00376         result=TRUE;
00377         *addr=len;
00378 #ifdef prlDEBUG
00379         amount_used+=len;
00380 #endif
00381       }
00382       else if (value < len && len != LONELY) {
00383         Errorline("in garbage collection, %d < %d.\n", value, len);
00384       }
00385       else if (value > len && len != LONELY) {
00386         Errorline("in garbage collection, %d > %d.\n", value, len);
00387       }
00388       break;
00389     case 2:
00390       if (value & 1) { /* If low bit set */
00391         value--;       /* Reset low bit */
00392         *addr=value;
00393 #ifdef prlDEBUG
00394         amount_used+=len;
00395 #endif
00396         result=TRUE;
00397       }
00398       if (!VALID_ADDRESS(value))
00399         assert(VALID_ADDRESS(value));
00400       *p = (GENERIC) value;
00401       break;
00402     }
00403   }
00404   return result;
00405 }
00406 
00407 
00408 
00409 /******** CHECK_STRING(s)
00410   Claim the memory used by the string S.
00411 */
00412 static void check_string (s)
00413 GENERIC *s;
00414 {
00415   GENERIC addr;
00416   long value;
00417   long bytes;
00418 
00419   if ((unsigned long) *s > MAX_BUILT_INS) {
00420     switch (pass) {
00421     case 1:
00422       bytes=strlen((char *)*s)+1;
00423       /* if (bytes==LONELY) {
00424         fprintf(stderr,"Caught an empty string!\n");
00425         fflush(stderr);
00426       } */
00427       /* Make sure there's no conflict with LONELY (this occurs for an */
00428       /* empty string, which still needs a single byte of storage). */
00429       /* This does occasionally happen. */
00430       unchecked(s, (bytes==LONELY)?bytes+1:bytes);
00431       break;
00432     case 2:
00433       addr=(*s+delta);
00434       value= *addr;
00435       if (value & 1) { /* If low bit set */
00436         value--;
00437         *s=(GENERIC)value;
00438         *addr=value;
00439 #ifdef prlDEBUG
00440         amount_used+=strlen(*s)+1;
00441 #endif
00442       }
00443       *s=(GENERIC)value;
00444       break;
00445     }
00446   }
00447 }
00448 
00449 /* DENYS: BYTEDATA */
00450 /******** CHECK_BYTEDATA(s)
00451   Claim the memory used by a block of bytes
00452   */
00453 static void check_bytedata(s)
00454      GENERIC *s;
00455 {
00456   GENERIC addr;
00457   long value;
00458   if ((unsigned long) *s > MAX_BUILT_INS) {
00459     unsigned long bytes = *((unsigned long *) *s);
00460     unsigned long size = bytes + sizeof(bytes);
00461     switch (pass) {
00462     case 1:
00463       unchecked(s,size);
00464       break;
00465     case 2:
00466       addr=(*s+delta);
00467       value= *addr;
00468       if (value & 1) {
00469         value--;
00470         *s=(GENERIC) value;
00471         *addr=value;
00472 #ifdef prlDEBUG
00473         amount_used+=size;
00474 #endif
00475       }
00476       *s=(GENERIC)value;
00477       break;
00478     }
00479   }
00480 }
00481 
00482 /******** CHECK_CODE(c)
00483   Claim the memory used by a type code (=list of integers).
00484 */
00485 static void check_code(c)
00486 ptr_int_list *c;
00487 {
00488   while (unchecked(c,sizeof(int_list)))
00489     c= &((*c)->next);
00490 }
00491 
00492 
00493 
00494 /******** CHECK_PAIR_LIST
00495   Checks a list of <GOAL,BODY> pairs.
00496 */
00497 static void check_pair_list(p)
00498 ptr_pair_list *p;
00499 {  
00500   while (unchecked(p,sizeof(pair_list))) {
00501     check_psi_term(&((*p)->a));
00502     check_psi_term(&((*p)->b));
00503     p= &((*p)->next);
00504   }
00505 }
00506 
00507 
00508 
00509 
00510 /******** CHECK_TRIPLE_LIST
00511   Checks a list of <GOAL,BODY,DEF> triples.
00512 */
00513 static void check_triple_list(p)
00514 ptr_triple_list *p;
00515 {  
00516   while (unchecked(p,sizeof(triple_list))) {
00517     check_psi_term(&((*p)->a));
00518     check_psi_term(&((*p)->b));
00519     check_definition(&((*p)->c));
00520     p= &((*p)->next);
00521   }
00522 }
00523 
00524 
00525 
00526 /******** CHECK_KIDS(c)
00527   Check a list of parents or children of a given type.
00528 */
00529 static void check_kids(c)
00530 ptr_int_list *c;
00531 {
00532   while (unchecked(c,sizeof(int_list))) {
00533     check_definition(&((*c)->value));
00534     c= &((*c)->next);
00535   }
00536 }
00537 
00538 
00539 
00540 /******** CHECK_OPERATOR_DATA(op)
00541   Explore a list of operator declarations.
00542 */
00543 static void check_operator_data(op)
00544 ptr_operator_data *op;
00545 {
00546   while (unchecked(op,sizeof(operator_data))) {
00547     op = &((*op)->next);
00548   }
00549 }
00550 
00551 
00552 static void check_module();
00553 void check_hash_table();          /*  RM: Feb  3 1993  */
00554 static void check_keyword();      /*  RM: Jan 12 1993  */
00555 
00556 
00557 
00558 /******** CHECK_MODULE_LIST(c)
00559   Check a list of modules.
00560 */
00561 
00562 static void check_module_list(c)    /*  RM: Jan 12 1993  */
00563      
00564      ptr_int_list *c;
00565 {
00566   while (unchecked(c,sizeof(int_list))) {
00567     check_module(&((*c)->value));
00568     c= &((*c)->next);
00569   }
00570 }
00571 
00572 
00573 /******** CHECK_MODULE_TREE
00574   This goes through the module table, checking all nodes.
00575 */
00576 static void check_module_tree(n)    /*  RM: Jan 13 1993  */
00577      ptr_node *n;
00578 {
00579   if (unchecked(n,sizeof(node))) {
00580     check_module_tree(&((*n)->left));
00581     check_string(&((*n)->key));
00582     check_module(&((*n)->data));
00583     check_module_tree(&((*n)->right));
00584   }
00585 }
00586 
00587 
00588 
00589 /******** CHECK_MODULE(m) 
00590   Checks a module.
00591   */
00592 
00593 static void check_module(m)        /*  RM: Jan 12 1993  */
00594      
00595      ptr_module *m;
00596 {
00597   if(unchecked(m,sizeof(struct wl_module))) {
00598     check_string(&((*m)->module_name));
00599     check_string(&((*m)->source_file));
00600     check_module_list(&((*m)->open_modules));
00601     check_module_list(&((*m)->inherited_modules));
00602     check_hash_table((*m)->symbol_table);
00603   }
00604 }
00605 
00606 
00607 
00608 /******** CHECK_HASH_TABLE(table)
00609   Check a hash table of keywords. The actual table is not stored within LIFE
00610   memory.
00611   */
00612 
00613 void check_hash_table(table) /*  RM: Feb  3 1993  */
00614      
00615      ptr_hash_table table;
00616 {
00617   long i;
00618   
00619   for(i=0;i<table->size;i++)
00620     if(table->data[i])
00621       check_keyword(&(table->data[i]));
00622 }
00623 
00624 
00625 
00626 /******** CHECK_KEYWORD(k)
00627   Checks a keyword.
00628   */
00629 
00630 static void check_keyword(k)      /*  RM: Jan 12 1993  */
00631      
00632      ptr_keyword *k;
00633 {
00634   if(unchecked(k,sizeof(struct wl_keyword))) {
00635     check_module(&((*k)->module));
00636     check_string(&((*k)->symbol));
00637     check_string(&((*k)->combined_name));
00638     check_definition(&((*k)->definition));
00639   }
00640 }
00641 
00642 
00643 
00644 /******** CHECK_DEFINITION
00645   This goes through the type tree which contains the parents and children lists
00646   for all types, and the attributed code. The code field is not checked as
00647   this has been done separately by CHECK_GAMMA.
00648 */
00649 void check_definition(d)
00650 ptr_definition *d;
00651 {  
00652   if(unchecked(d,sizeof(definition))) {
00653     
00654     check_keyword(&((*d)->keyword)); /*  RM: Jan 12 1993  */
00655     
00656 #ifdef prlDEBUG
00657     printf("%lx %20s %ld\n",*d,(*d)->keyword->symbol,amount_used);
00658 #endif
00659 
00660     check_code(&((*d)->code));
00661     check_pair_list(&((*d)->rule));
00662     check_triple_list(&((*d)->properties));
00663     
00664     if ((*d)->type==type) {
00665       check_kids(&((*d)->parents));
00666       check_kids(&((*d)->children));
00667     }
00668 
00669     check_psi_term(&((*d)->global_value)); /*  RM: Feb  9 1993  */
00670     check_psi_term(&((*d)->init_value));   /*  RM: Mar 23 1993  */
00671     
00672     check_operator_data(&((*d)->op_data)); /* PVR 5.6 */
00673 
00674 #ifdef CLIFE
00675     check_block_def(&((*d)->block_def)); /*  RM: Jan 27 1993  */
00676 #endif /* CLIFE */
00677   }
00678 }
00679 
00680 
00681 
00682 /******** CHECK_DEFINITION_LIST
00683   This checks the entire list of definitions.
00684 */
00685 void check_definition_list()   /*  RM: Feb 15 1993  */
00686 
00687 {
00688   ptr_definition *d;
00689 
00690   d= &first_definition;
00691 
00692   while(*d) {
00693     check_definition(d);
00694     d= &((*d)->next);
00695   }
00696 }
00697 
00698 
00699 
00700 /******** CHECK_DEF_CODE(d)
00701   This routine checks the CODE field in a definition.
00702   It may only be invoked by CHECK_GAMMA.
00703 */
00704 static void check_def_code(d)
00705 ptr_definition *d;
00706 {  
00707   if (unchecked(d,sizeof(definition)))
00708     check_code(&((*d)->code));
00709   /* p = &((*d)->properties); */
00710   /* check_def_prop(p); */
00711 }
00712 
00713 
00714 
00715 /******** CHECK_DEF_REST(d)
00716   This routine checks the other fields in a definition.
00717   It may only be invoked by CHECK_GAMMA_REST.
00718 */
00719 static void check_def_rest(d)
00720 ptr_definition *d;
00721 {
00722   if (*d) {
00723     check_keyword(&((*d)->keyword)); /*  RM: Jan 12 1993  */
00724     check_pair_list(&((*d)->rule));
00725     check_triple_list(&((*d)->properties));
00726     
00727     if ((*d)->type==type) {
00728       check_kids(&((*d)->parents));
00729       check_kids(&((*d)->children));
00730     }
00731     check_operator_data(&((*d)->op_data)); /* PVR 5.6 */
00732 #ifdef CLIFE
00733     check_block_def(&((*d)->block_def));  /*CB 25/01/93 */
00734 #endif /* CLIFE */
00735   }
00736 }
00737 
00738 
00739 
00740 /******** CHECK_SYMBOL
00741   This goes through the symbol table, checking all nodes, symbols, strings
00742   and definitions not contained in the type table.
00743 */
00744 static void check_symbol(n)
00745 ptr_node *n;
00746 {
00747   if (unchecked(n,sizeof(node))) {
00748     check_symbol(&((*n)->left));
00749     check_string(&((*n)->key));
00750     check_keyword(&((*n)->data));   /*  RM: Jan 12 1993  */
00751     check_symbol(&((*n)->right));
00752   }
00753 }
00754 
00755 
00756 
00757 /******** CHECK_TYPE_DISJ
00758   Checks the list of definitions appearing in a type disjunction.
00759 */
00760 static void check_type_disj(p)
00761 ptr_int_list *p;
00762 {  
00763   while (unchecked(p,sizeof(int_list))) {
00764     check_definition(&((*p)->value));
00765     p= &((*p)->next);
00766   }
00767 }
00768 
00769 
00770 
00771 /******** CHECK_GOAL_STACK
00772   Check the goal_stack. This is quite complicated as each type of goal (prove,
00773   unify, eval, eval_cut etc...) gives its own meanings to the three other
00774   fields (A,B and C) present in each goal.
00775 */
00776 static void check_goal_stack(g)
00777 ptr_goal *g;
00778 {
00779   while (unchecked(g,sizeof(goal))) {
00780     
00781     switch ((*g)->type) {
00782       
00783     case fail:
00784       break;
00785       
00786     case unify:
00787     case unify_noeval: /* PVR 5.6 */
00788       check_psi_term(&((*g)->a));
00789       check_psi_term(&((*g)->b));
00790       break;
00791       
00792     case prove:
00793       check_psi_term(&((*g)->a));
00794       if ((unsigned long)(*g)->b!=DEFRULES) check_pair_list(&((*g)->b));
00795       check_pair_list(&((*g)->c));
00796       break;
00797       
00798     case disj: 
00799       check_psi_term(&((*g)->a));
00800       check_psi_term(&((*g)->b));
00801       break;
00802       
00803     case what_next:
00804       /* check_choice(&((*g)->b)); */
00805       break;
00806       
00807     case eval: 
00808       check_psi_term(&((*g)->a));
00809       check_psi_term(&((*g)->b));
00810       check_pair_list(&((*g)->c));
00811       break;
00812 
00813     case load:
00814       check_psi_term(&((*g)->a));
00815       check_string(&((*g)->c));
00816       break;
00817       
00818     case match:
00819       check_psi_term(&((*g)->a));
00820       check_psi_term(&((*g)->b));
00821       check_resid_block(&((*g)->c));
00822       break;
00823 
00824     case general_cut:
00825       /* assert((GENERIC)(*g)->a <= (GENERIC)choice_stack); 12.7 17.7 */
00826       if (pass==1 && (ptr_choice_point)(*g)->a>choice_stack)
00827         (*g)->a=(ptr_psi_term)choice_stack;
00828       unchecked(&((*g)->a),LONELY);
00829       break;
00830       
00831     case eval_cut:
00832       check_psi_term(&((*g)->a));
00833       /* assert((GENERIC)(*g)->b <= (GENERIC)choice_stack); 12.7 17.7 */
00834       if (pass==1 && (ptr_choice_point)(*g)->b>choice_stack)
00835         (*g)->b=(ptr_psi_term)choice_stack;
00836       unchecked(&((*g)->b),LONELY);
00837       check_resid_block(&((*g)->c));
00838       break;
00839 
00840     case freeze_cut:
00841     case implies_cut:
00842       check_psi_term(&((*g)->a));
00843       /* assert((GENERIC)(*g)->b <= (GENERIC)choice_stack); 12.7 17.7 */
00844       if (pass==1 && (ptr_choice_point)(*g)->b>choice_stack)
00845         (*g)->b=(ptr_psi_term)choice_stack;
00846       unchecked(&((*g)->b),LONELY);
00847       check_resid_block(&((*g)->c));
00848       break;
00849       
00850     case type_disj:
00851       check_psi_term(&((*g)->a));
00852       check_type_disj(&((*g)->b));
00853       break;
00854       
00855     case clause:
00856       check_psi_term(&((*g)->a));
00857       check_psi_term(&((*g)->b));
00858       unchecked(&((*g)->c),LONELY);
00859       /* check_pair_list((*g)->c); */ /* 6.8 */
00860       break;
00861 
00862     case del_clause:
00863       check_psi_term(&((*g)->a));
00864       check_psi_term(&((*g)->b));
00865       unchecked(&((*g)->c),LONELY);
00866       /* check_pair_list((*g)->c); */ /* 6.8 */
00867       break;
00868 
00869     case retract:
00870       unchecked(&((*g)->a),LONELY);
00871       /* check_pair_list((*g)->a); */ /* 6.8 */
00872       /*PVR*/ /* check_choice(&((*g)->b)); 9.6 */
00873       break;
00874 
00875     default:
00876       Errorline("in garbage collection, bad goal on stack.\n");
00877     }
00878     
00879     g= &((*g)->next);
00880   }
00881 }
00882 
00883 
00884 
00885 /******** CHECK_RESID(r)
00886   Explore a list of residuations.
00887 */
00888 static void check_resid(r)
00889 ptr_residuation *r;
00890 {
00891   ptr_int_list code;
00892   ptr_list *l;
00893 
00894   while (unchecked(r,sizeof(residuation))) {
00895 
00896     if ((*r)->sortflag) /* 22.9 */
00897       check_definition(&((*r)->bestsort));
00898     else
00899       check_code(&((*r)->bestsort)); /* 21.9 */
00900 
00901     /* Handling of the value field (6.10) */
00902     code = (*r)->sortflag ? ((ptr_definition)((*r)->bestsort))->code
00903                           : (ptr_int_list)(*r)->bestsort;
00904     /* Copied (almost) verbatim from check_psi_term: */
00905     if ((*r)->value) {
00906       if (code==alist->code) { /*  RM: Dec 15 1992  Will be removed */
00907         l=(ptr_list *) &((*r)->value);
00908         if (l)
00909           printf("Found an old list!!\n");
00910       }
00911       else if (sub_CodeType(code,real->code))
00912         unchecked(&((*r)->value),sizeof(REAL));
00913       else if (sub_CodeType(code,quoted_string->code))
00914         check_string(&((*r)->value));
00915       /* DENYS: BYTEDATA */
00916       else if (sub_CodeType(code,sys_bytedata->code))
00917         check_bytedata(&((*r)->value));
00918       else if (sub_CodeType(code,cut->code)) {
00919         if (pass==1 && (*r)->value>(GENERIC)choice_stack)
00920           (*r)->value=(GENERIC)choice_stack;
00921         unchecked(&((*r)->value),LONELY);
00922       }
00923       else if (sub_CodeType(code,variable->code)) /* 8.8 */
00924         check_string(&((*r)->value));
00925     }
00926 
00927     check_goal_stack(&((*r)->goal));
00928     r= &((*r)->next);
00929   }
00930 }
00931 
00932 
00933 
00934 /******** CHECK_RESID_BLOCK(rb)
00935   Explore a residuation block.
00936 */
00937 void check_resid_block(rb)
00938 ptr_resid_block *rb;
00939 {
00940   if (*rb) {
00941     if (unchecked(rb,sizeof(resid_block))) {
00942       check_goal_stack(&((*rb)->ra));
00943       check_resid_list(&((*rb)->rv)); /* 21.9 */
00944       /* unchecked(&((*rb)->rl),LONELY); 12.6 */  /* 10.6 */
00945       unchecked(&((*rb)->md),LONELY); /* 10.6 */
00946       /* check_goal_stack(&((*rb)->rl)); 10.6 */
00947       /* check_psi_term(&((*rb)->md)); 10.6 */
00948     }
00949   }
00950 }
00951 
00952 
00953 
00954 /******** CHECK_PSI_TERM(t)
00955   Explore a psi_term.
00956 */
00957 void check_psi_term(t)
00958 ptr_psi_term *t;
00959 {
00960   ptr_list *l;
00961 
00962   while (unchecked(t,sizeof(psi_term))) {
00963       
00964     /* A psi-term on the heap has no residuation list. */
00965     if (pass==1 && (GENERIC)(*t)>=heap_pointer && (GENERIC)(*t)<mem_limit) {
00966       assert((*t)->resid==NULL);
00967     }
00968     check_definition(&((*t)->type));
00969     check_attr(&((*t)->attr_list));
00970     
00971     if ((*t)->value) {
00972 
00973       if ((*t)->type==alist) { /*  RM: Dec 15 1992  Should be removed  */
00974         l=(ptr_list *) &((*t)->value);
00975         if (l)
00976           printf("Found an old list!\n");
00977       }
00978       else
00979 
00980         if (sub_type((*t)->type,real))
00981           unchecked(&((*t)->value),sizeof(REAL));
00982         else if (sub_type((*t)->type,quoted_string))
00983           check_string(&((*t)->value));
00984       /* DENYS: BYTEDATA */
00985         else if (sub_type((*t)->type,sys_bytedata))
00986           check_bytedata(&((*t)->value));
00987 #ifdef CLIFE
00988         else if ((*t)->type->type==block) {  /*  RM: Jan 27 1993  */
00989           check_block_value(&((*t)->value));
00990         }
00991 #endif /* CLIFE */
00992         else if ((*t)->type==cut) { /*  RM: Oct 28 1993  */
00993           /* assert((*t)->value <= (GENERIC)choice_stack); 12.7 17.7 */
00994           if (pass==1 && (*t)->value>(GENERIC)choice_stack)
00995             (*t)->value=(GENERIC)choice_stack;
00996           unchecked(&((*t)->value),LONELY);
00997         }
00998         else if (sub_type((*t)->type,variable)) /* 8.8 */
00999           check_string(&((*t)->value));
01000         else if ((*t)->type!=stream)
01001           Errorline("non-NULL value field in garbage collector, type='%s', value=%d.\n",
01002                     (*t)->type->keyword->combined_name,
01003                     (*t)->value);
01004     }
01005     
01006     /* check_psi_term(&((*t)->coref)); 9.6 */
01007     if ((*t)->resid)
01008       check_resid(&((*t)->resid));
01009     
01010     t = &((*t)->coref);
01011   }
01012 }
01013 
01014 
01015 
01016 /******** CHECK_ATTR(attribute-tree)
01017   Check an attribute tree.
01018   (Could improve this by randomly picking left or right subtree
01019   for last call optimization.  This would never overflow, even on
01020   very skewed attribute trees.)
01021 */
01022 void check_attr(n)
01023 ptr_node *n;
01024 {
01025   while (unchecked(n,sizeof(node))) {
01026     check_attr(&((*n)->left));
01027     check_string(&((*n)->key));
01028     check_psi_term(&((*n)->data));
01029 
01030     n = &((*n)->right);
01031     /* check_attr(&((*n)->right)); 9.6 */
01032   }
01033 }
01034 
01035 
01036 
01037 /******** CHECK_GAMMA_CODE()
01038   Check and update the code
01039   reversing table.  In this part, only the codes are checked in
01040   the definitions, this is vital because these codes are used
01041   later to distinguish between the various data types and to
01042   determine the type of the VALUE field in psi_terms. Misunderstanding this
01043   caused a lot of bugs in the GC.
01044 */
01045 void check_gamma_code()
01046 {
01047   long i;
01048 
01049   if (unchecked(&gamma_table,type_count*sizeof(ptr_definition))) {
01050     for (i=0;i<type_count;i++)
01051       check_def_code(&(gamma_table[i]));
01052   }
01053 }
01054 
01055 
01056 
01057 /******** CHECK_GAMMA_REST()
01058   Check and update the code reversing table.
01059 */
01060 static void check_gamma_rest()
01061 {
01062   long i;
01063 
01064   for (i=0;i<type_count;i++)
01065     check_def_rest(&(gamma_table[i]));
01066 }
01067 
01068 
01069 
01070 /******** CHECK_UNDO_STACK()
01071   This looks after checking the addresses of objects pointed to in the trail.
01072   The type of the pointer to be restored on backtracking is known, which
01073   allows the structure it is referring to to be accordingly checked.
01074 */
01075 static void check_undo_stack(s)
01076 ptr_stack *s;
01077 {
01078   while (unchecked(s,sizeof(stack))) {
01079        
01080     switch((*s)->type) {
01081       
01082     case psi_term_ptr:
01083       check_psi_term(&((*s)->b));
01084       break;
01085       
01086     case resid_ptr:
01087       check_resid(&((*s)->b));
01088       break;
01089       
01090     case int_ptr:
01091       /* int_ptr's are used to trail time_stamps, so they can get large. */
01092       break;
01093       
01094     case def_ptr:
01095       check_definition(&((*s)->b));
01096       break;
01097       
01098     case code_ptr:
01099       check_code(&((*s)->b));
01100       break;
01101 
01102     case goal_ptr:
01103       check_goal_stack(&((*s)->b));
01104       break;
01105 
01106     case cut_ptr: /* 22.9 */
01107       break;
01108 #ifdef CLIFE
01109     case block_ptr: /*  CB: Jan 28 1993  */
01110       check_block_value(&((*s)->b));
01111       break;
01112 
01113 #endif /* CLIFE */
01114     /* All undo actions here */
01115     case destroy_window:
01116     case show_window:
01117     case hide_window:
01118       /* No pointers to follow */
01119       break;
01120     }
01121 
01122     s= &((*s)->next);
01123   }
01124 }
01125 
01126 
01127 
01128 /******** CHECK_CHOICE(c)
01129   This routine checks all choice points.
01130 */
01131 static void check_choice_structs(c)
01132      ptr_choice_point *c;
01133 {
01134   while(unchecked(c,sizeof(choice_point))) {
01135     c= &((*c)->next);
01136   }
01137 }
01138 
01139 static void check_choice(c)
01140      ptr_choice_point *c;
01141 {
01142   while(*c) {
01143     check_undo_stack(&((*c)->undo_point)); /* 17.7 */
01144     check_goal_stack(&((*c)->goal_stack));
01145     c= &((*c)->next);
01146   }
01147 }
01148 
01149 
01150 
01151 /******** CHECK_SPECIAL_ADDRESSES
01152   Here we check all the addresses which do not point to a whole data structure,
01153   but to something within, for example a field such as VALUE which might
01154   have been modified in a PSI_TERM structure.  These are the LONELY addresses.
01155 */
01156 static void check_special_addresses()
01157 {
01158   ptr_choice_point c;
01159   ptr_stack p;
01160   ptr_goal g;
01161 
01162   c=choice_stack;
01163   while(c) {
01164     /* unchecked(&(c->undo_point),LONELY); 17.7 */
01165     unchecked(&(c->stack_top),LONELY);
01166     c=c->next;
01167   }
01168 
01169   p=undo_stack;
01170   while (p) {
01171     if (!(p->type & undo_action)) {
01172       /* Only update an address if it's within the Life data space! */
01173       if (VALID_RANGE(p->a)) unchecked(&(p->a),LONELY);
01174       if (p->type==cut_ptr) unchecked(&(p->b),LONELY); /* 22.9 */
01175     }
01176     p=p->next;
01177   }
01178 }
01179 
01180 
01181 
01182 /******** CHECK_PSI_LIST
01183   Update all the values in the list of residuation variables, which is a list
01184   of psi_terms.
01185 */
01186 static void check_psi_list(l)
01187 ptr_int_list *l;
01188 {
01189   while(unchecked(l,sizeof(int_list))) {
01190     check_psi_term(&((*l)->value));
01191     l= &((*l)->next);
01192   }
01193 }
01194 
01195 
01196 
01197 /******** CHECK_RESID_LIST
01198   Update all the values in the list of residuation variables, which is a list
01199   of pairs of psi_terms.
01200 */
01201 static void check_resid_list(l)
01202 ptr_resid_list *l;
01203 {
01204   while(unchecked(l,sizeof(resid_list))) {
01205     check_psi_term(&((*l)->var));
01206     check_psi_term(&((*l)->othervar));
01207     l= &((*l)->next);
01208   }
01209 }
01210 
01211 
01212 
01213 /******** CHECK_VAR(t)
01214   Go through the VARiable tree.
01215   (This could be made tail recursive.)
01216 */
01217 static void check_var(n)
01218 ptr_node *n;
01219 {
01220   if (unchecked(n,sizeof(node))) {
01221     check_var(&((*n)->left));
01222     check_string(&((*n)->key));
01223     check_psi_term(&((*n)->data));
01224     check_var(&((*n)->right));
01225   }
01226 }
01227 
01228 
01229 
01230 /******** CHECK
01231   This routine checks all pointers and psi_terms to find out which memory cells
01232   must be preserved and which can be discarded.
01233 
01234   This routine explores all known structures. It is vital that it should visit
01235   them all exactly once. It thus creates a map of what is used in memory, which
01236   COMPRESS uses to compact the memory and recalculate the addresses.
01237   Exploration of these structures should be done in exactly the same order
01238   in both passes. If it is the second pass, pointers are assigned their new
01239   values.
01240 
01241   A crucial property of this routine: In pass 2, a global variable (i.e. a
01242   root for GC) must be updated before it is accessed.  E.g. don't use the
01243   variable goal_stack before updating it.
01244 */
01245 static void check()
01246 {
01247 #ifdef prlDEBUG
01248   amount_used=0;
01249 #endif
01250 
01251   /* First of all, get all the codes right so that data type-checking remains
01252      coherent.
01253 
01254      Kids and Parents cannot be checked because the built-in types have codes
01255      which might have been moved.
01256   */
01257   /* print_undo_stack(); */
01258 
01259   
01260   check_choice_structs(&choice_stack); /*  RM: Oct 28 1993  */
01261   
01262   assert((pass==1?bounds_undo_stack():TRUE));
01263   check_gamma_code();
01264   
01265   /* Now, check the rest of the definitions and all global roots */
01266   
01267   check_gamma_rest();
01268 
01269   assert((pass==1?bounds_undo_stack():TRUE));
01270 
01271   check_definition(&abortsym); /* 26.1 */
01272   check_definition(&aborthooksym); /* 26.1 */
01273 
01274   check_definition(&add_module1); /*  RM: Mar 12 1993  */
01275   check_definition(&add_module2);
01276   check_definition(&add_module3);
01277     
01278   check_definition(&and);
01279   check_definition(&apply);
01280   check_definition(&boolean);
01281   check_definition(&boolpredsym);
01282   check_definition(&built_in);
01283   check_definition(&colonsym);
01284   check_definition(&commasym);
01285   check_definition(&comment);
01286   /* check_definition(&conjunction); 19.8 */
01287   check_definition(&constant);
01288   check_definition(&cut);
01289   check_definition(&disjunction);
01290   check_definition(&disj_nil);  /*  RM: Feb 16 1993  */
01291   check_definition(&eof);
01292   check_definition(&eqsym);
01293   check_definition(&false);
01294   check_definition(&funcsym);
01295   check_definition(&functor);
01296   check_definition(&iff);
01297   check_definition(&integer);
01298   check_definition(&alist);
01299   check_definition(&life_or); /*  RM: Apr  6 1993  */
01300   check_definition(&minus_symbol); /*  RM: Jun 21 1993  */
01301   check_definition(&nil); /*  RM: Dec  9 1992  */
01302   check_definition(&nothing);
01303   check_definition(&predsym);
01304   check_definition(&quote);
01305   check_definition(&quoted_string);
01306   check_definition(&real);
01307   check_definition(&stream);
01308   check_definition(&succeed);
01309   check_definition(&such_that);
01310   check_definition(&top);
01311   check_definition(&true);
01312   check_definition(&timesym);
01313   check_definition(&tracesym); /* 26.1 */
01314   check_definition(&typesym);
01315   check_definition(&variable);
01316   check_definition(&opsym);
01317   check_definition(&loadsym);
01318   check_definition(&dynamicsym);
01319   check_definition(&staticsym);
01320   check_definition(&encodesym);
01321   check_definition(&listingsym);
01322   /* check_definition(&provesym); */
01323   check_definition(&delay_checksym);
01324   check_definition(&eval_argsym);
01325   check_definition(&inputfilesym);
01326   check_definition(&call_handlersym);
01327   check_definition(&xf_sym);
01328   check_definition(&fx_sym);
01329   check_definition(&yf_sym);
01330   check_definition(&fy_sym);
01331   check_definition(&xfx_sym);
01332   check_definition(&xfy_sym);
01333   check_definition(&yfx_sym);
01334   check_definition(&nullsym);
01335 
01336   /*  RM: Jul  7 1993  */
01337   check_definition(&final_dot);
01338   check_definition(&final_question);
01339 
01340   check_sys_definitions();
01341   
01342 #ifdef X11
01343   check_definition(&xevent);
01344   check_definition(&xmisc_event);
01345   check_definition(&xkeyboard_event);
01346   check_definition(&xbutton_event);
01347   check_definition(&xconfigure_event);
01348   check_definition(&xmotion_event);
01349   check_definition(&xenter_event);
01350   check_definition(&xleave_event);
01351   check_definition(&xexpose_event);
01352   check_definition(&xdestroy_event);
01353   check_definition(&xdisplay);
01354   check_definition(&xdrawable);
01355   check_definition(&xwindow);
01356   check_definition(&xpixmap);
01357   check_definition(&xgc);
01358   check_definition(&xdisplaylist);
01359 #endif
01360   
01361   /* check_psi_term(&empty_list); 5.8 */
01362   
01363   check_string(&one);
01364   check_string(&two);
01365   check_string(&three);
01366   check_string(&year_attr);
01367   check_string(&month_attr);
01368   check_string(&day_attr);
01369   check_string(&hour_attr);
01370   check_string(&minute_attr);
01371   check_string(&second_attr);
01372   check_string(&weekday_attr);
01373 
01374   check_psi_term(&input_state);
01375   check_psi_term(&stdin_state);
01376   check_psi_term(&error_psi_term);
01377   check_psi_term(&saved_psi_term);
01378   check_psi_term(&old_saved_psi_term);
01379   check_psi_term(&null_psi_term);
01380   check_psi_term(&old_state); /*  RM: Feb 17 1993  */
01381 
01382   assert((pass==1?bounds_undo_stack():TRUE));
01383 #ifdef X11
01384   check_psi_term(&xevent_list);
01385   check_psi_term(&xevent_existing);
01386 #endif
01387 
01388   check_choice(&choice_stack);
01389   /* check_choice(&prompt_choice_stack); 12.7 */
01390 
01391 
01392   /*  RM: Feb  3 1993  */
01393   /* check_symbol(&symbol_table); */
01394   /* check_definition(&first_definition); */
01395   check_definition_list(); /*  RM: Feb 15 1993  */
01396 
01397   
01398   /*** MODULES ***/
01399   /*  RM: Jan 13 1993  */
01400 
01401   check_module_tree(&module_table);
01402   check_module(&sys_module);
01403   check_module(&bi_module);
01404   check_module(&user_module);  /*  RM: Jan 27 1993  */
01405   check_module(&no_module);
01406   check_module(&x_module);
01407   check_module(&syntax_module);
01408   check_module(&current_module);
01409   
01410   /*** End ***/
01411 
01412 
01413   
01414   check_var(&var_tree);
01415 
01416   check_goal_stack(&goal_stack);
01417   check_goal_stack(&aim); /* 7.10 */
01418 
01419   if (TRUE /*resid_aim 10.6 */) check_resid_list(&resid_vars); /* 21.9 */
01420   
01421   check_goal_stack(&resid_aim);
01422 
01423   assert((pass==1?bounds_undo_stack():TRUE));
01424   check_undo_stack(&undo_stack);
01425 
01426   assert((pass==1?bounds_undo_stack():TRUE));
01427   check_special_addresses();
01428 
01429   assert((pass==1?bounds_undo_stack():TRUE));
01430 }
01431 
01432 
01433 void print_gc_info(timeflag)
01434 long timeflag;
01435 {
01436   fprintf(stderr," [%ld%% free (%ldK), %ld%% heap, %ld%% stack",
01437           (100*((unsigned long)heap_pointer-(unsigned long)stack_pointer)+mem_size/2)/mem_size,
01438           ((unsigned long)heap_pointer-(unsigned long)stack_pointer+512)/1024,
01439           (100*((unsigned long)mem_limit-(unsigned long)heap_pointer)+mem_size/2)/mem_size,
01440           (100*((unsigned long)stack_pointer-(unsigned long)mem_base)+mem_size/2)/mem_size);
01441   if (timeflag) {
01442     fprintf(stderr,", %1.3fs cpu (%ld%%)",
01443             gc_time,
01444             (unsigned long)(0.5+100*gc_time/(life_time+gc_time)));
01445   }
01446   fprintf(stderr,"]\n");
01447 }
01448 
01449 
01450 /******** GARBAGE()
01451   The garbage collector.
01452   This routine is called whenever memory is getting low.
01453   It returns TRUE if insufficient memory was freed to allow
01454   the interpreter to carry on working.
01455 
01456   This is a half-space GC, it first explores all known structures, then
01457   compresses the heap and the stack, then during the second pass assigns
01458   all the new addresses.
01459   
01460   Bugs will appear if the collector is called during parsing or other
01461   such routines which are 'unsafe'. In order to avoid this problem, before
01462   one of these routines is invoked the program will check to see whether
01463   there is enough memory available to work, and will call the GC if not
01464   (this is a fix, because it is not possible to determine in advance
01465   what the size of a psi_term read by the parser will be).
01466 */
01467 void garbage()
01468 {
01469   GENERIC addr;
01470 #ifndef OS2_PORT
01471   struct tms garbage_start_time,garbage_end_time;
01472 #else
01473   float garbage_start_time,garbage_end_time;
01474 #endif
01475   long start_number_cells, end_number_cells;
01476 
01477   start_number_cells = (stack_pointer-mem_base) + (mem_limit-heap_pointer);
01478 
01479   times(&garbage_start_time);
01480 
01481   /* Time elapsed since last garbage collection */
01482 #ifndef OS2_PORT
01483   life_time=(garbage_start_time.tms_utime - last_garbage_time.tms_utime)/60.0;
01484 #else
01485   life_time=(garbage_start_time - last_garbage_time)/60.0;
01486 #endif
01487 
01488   if (verbose) {
01489     fprintf(stderr,"*** Garbage Collect "); /*  RM: Jan 26 1993  */
01490     fprintf(stderr,"\n*** Begin");
01491     print_gc_info(FALSE);
01492     fflush(stderr);
01493   }
01494 
01495   
01496   /* reset the other base */
01497   for (addr = other_base; addr < other_limit; addr ++)
01498     *addr = 0;
01499 
01500   pass=1;
01501 
01502   check();
01503 #ifdef GCVERBOSE
01504   fprintf(stderr,"- Done pass 1 ");
01505 #endif
01506 
01507   assert(bounds_undo_stack());
01508   compress();
01509 #ifdef GCVERBOSE
01510   fprintf(stderr,"- Done compress ");
01511 #endif
01512 
01513   pass=2;
01514 
01515   check();
01516   assert(bounds_undo_stack());
01517 #ifdef GCVERBOSE
01518   fprintf(stderr,"- Done pass 2\n");
01519 #endif
01520 
01521   clear_copy();
01522 
01523   printed_pointers=NULL;
01524   pointer_names=NULL;
01525   
01526   times(&garbage_end_time);
01527 #ifndef OS2_PORT
01528   gc_time=(garbage_end_time.tms_utime - garbage_start_time.tms_utime)/60.0;
01529 #else
01530   gc_time=(garbage_end_time - garbage_start_time)/60.0;
01531 #endif
01532   garbage_time+=gc_time;
01533 
01534   if (verbose) {
01535     fprintf(stderr,"*** End  ");
01536     print_gc_info(TRUE); /*  RM: Jan 26 1993  */
01537     stack_info(stderr);
01538     fflush(stderr);
01539   }
01540 
01541   last_garbage_time=garbage_end_time;
01542 
01543   end_number_cells = (stack_pointer-mem_base) + (mem_limit-heap_pointer);
01544   assert(end_number_cells<=start_number_cells);
01545   
01546   ignore_eff=FALSE;
01547 
01548 }
01549 
01550 
01551 
01552 /****************************************************************************
01553 
01554   MEMORY ALLOCATION ROUTINES.
01555 
01556 */
01557 
01558 
01559 
01560 /******** HEAP_ALLOC(s)
01561   This returns a pointer to S bytes of memory in the heap.
01562   Alignment is taken into account in the following manner:
01563   the macro ALIGN is supposed to be a power of 2 and the pointer returned
01564   is a multiple of ALIGN.
01565 */
01566 GENERIC heap_alloc (s)
01567 long s;
01568 {
01569     if (s & (ALIGN-1))
01570       s = s - (s & (ALIGN-1))+ALIGN;
01571     /* assert(s % sizeof(*heap_pointer) == 0); */
01572     s /= sizeof (*heap_pointer);
01573   
01574     heap_pointer -= s;
01575 
01576     if (stack_pointer>heap_pointer)
01577       Errorline("the heap overflowed into the stack.\n");
01578 
01579     return heap_pointer;
01580 }
01581 
01582 
01583 
01584 /******** STACK_ALLOC(s)
01585   This returns a pointer to S bytes of memory in the stack.
01586   Alignment is taken into account in the following manner:
01587   the macro ALIGN is supposed to be a power of 2 and the pointer returned
01588   is a multiple of ALIGN.
01589 */
01590 GENERIC stack_alloc(s)
01591 long s;
01592 {
01593     GENERIC r;
01594 
01595     r = stack_pointer;
01596 
01597     if (s & (ALIGN-1))
01598       s = s - (s & (ALIGN-1)) + ALIGN;
01599     /* assert(s % sizeof(*stack_pointer) == 0); */
01600     s /= sizeof (*stack_pointer);
01601 
01602     stack_pointer += s;
01603 
01604     if (stack_pointer>heap_pointer)
01605       Errorline("the stack overflowed into the heap.\n");
01606   
01607     return r;
01608 }
01609 
01610 
01611 
01612 /******** INIT_MEMORY()
01613   Get two big blocks of memory to work in.
01614   The second is only used for the half-space garbage collector.
01615   The start and end addresses of the blocks are re-aligned correctly.
01616   to allocate.  
01617 */
01618 
01619 
01620 void init_memory ()
01621 {
01622   alloc_words=GetIntOption("memory",ALLOC_WORDS);
01623   mem_size=alloc_words*sizeof(long);
01624   
01625   mem_base   = (GENERIC) malloc(mem_size);
01626   other_base = (GENERIC) malloc(mem_size);
01627 
01628   if (mem_base && other_base) {
01629     /* Rewrote some rather poor code... RM: Mar  1 1994  */
01630     ALIGNUP(mem_base);
01631     stack_pointer = mem_base;
01632     
01633     mem_limit=mem_base+alloc_words-2;
01634     ALIGNUP(mem_limit);
01635     heap_pointer = mem_limit;
01636 
01637     ALIGNUP(other_base);
01638     other_pointer = other_base;
01639 
01640     other_limit=other_base+alloc_words-2;
01641     ALIGNUP(other_limit);
01642     
01643     delta = other_base - mem_base;
01644     buffer = (char *) malloc (PRINT_BUFFER); /* The printing buffer */
01645 
01646     /*  RM: Oct 22 1993  */
01647     /* Fill the memory with rubbish data */
01648     /*
01649     {
01650       int i;
01651       
01652       for(i=0;i<alloc_words;i++) {
01653         mem_base[i]= -1234;
01654         other_base[i]= -1234;
01655       }
01656     }
01657     */
01658   }
01659   else
01660     Errorline("Wild_life could not allocate sufficient memory to run.\n\n");
01661 }
01662 
01663 
01664 
01665 /******** MEMORY_CHECK()
01666   This function tests to see whether enough memory is available to allow
01667   execution to continue.  It causes a garbage collection if not, and if that
01668   fails to release enough memory it returns FALSE.
01669 */
01670 long memory_check ()
01671 {
01672   long success=TRUE;
01673   
01674   if (heap_pointer-stack_pointer < GC_THRESHOLD) {
01675     if(verbose) fprintf(stderr,"\n"); /*  RM: Feb  1 1993  */
01676     garbage();
01677     /* Abort if didn't recover at least GC_THRESHOLD/10 of memory */
01678     if (heap_pointer-stack_pointer < GC_THRESHOLD+GC_THRESHOLD/10) {
01679       fprintf(stderr,"*********************\n");
01680       fprintf(stderr,"*** OUT OF MEMORY ***\n");
01681       fprintf(stderr,"*********************\n");
01682       fail_all();
01683       success=FALSE;
01684     }
01685   }
01686   return success;
01687 }
01688 
01689 
01690 

Generated on Sat Jan 26 08:48:07 2008 for WildLife by  doxygen 1.5.4