# define NUMWORDS TTSIZE * 128 /* max number of words in P0 space */
# define BITQUADS TTSIZE * 2 /* length of bit map in quad words */
# define ftstbit asm(" ashl $-2,r11,r3");\
asm(" bbcs r3,_bitmapq,$1");\
/* define ftstbit if( readbit(p) ) return; oksetbit; */
# define readbit(p) ((int)bitmap[r=(int)p>>5] & (s=bitmsk[((int)p>>2)&7]))
# define lookbit(p) (bitmap[(int)p>>5] & bitmsk[((int)p>>2) & 7])
# define setbit(p) {bitmap[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
# define oksetbit {bitmap[r] |= s;}
# define readchk(p) ((int)bitfre[(int)p>>5] & bitmsk[((int)p>>2)&7])
# define setchk(p) {bitfre[(int)p>>5] |= bitmsk[((int)p >> 2) & 7];}
FILE * chkport
; /* garbage collection dump file */
lispval datalim
; /* end of data space */
double bitmapq
[BITQUADS
]; /* the bit map--one bit per long */
double zeroq
; /* a quad word of zeros */
char *bitmap
= (char *) bitmapq
; /* byte version of bit map array */
char bitmsk
[8]={1,2,4,8,16,32,64,128}; /* used by bit-marking macros */
int *bind_lists
= (int *) CNIL
; /* lisp data for compiled code */
type_len
; /* note type_len is in units of int */
} atom_str
= {(char *)CNIL
,0,ATOMSPP
,ATOM
,5,&atom_items
,&atom_pages
,&atom_name
,(struct heads
*)CNIL
},
strng_str
= {(char *)CNIL
,0,STRSPP
,STRNG
,1,&str_items
,&str_pages
,&str_name
,(struct heads
*)CNIL
},
int_str
= {(char *)CNIL
,0,INTSPP
,INT
,1,&int_items
,&int_pages
,&int_name
,(struct heads
*)CNIL
},
dtpr_str
= {(char *)CNIL
,0,DTPRSPP
,DTPR
,2,&dtpr_items
,&dtpr_pages
,&dtpr_name
,(struct heads
*)CNIL
},
doub_str
= {(char *)CNIL
,0,DOUBSPP
,DOUB
,2,&doub_items
,&doub_pages
,&doub_name
,(struct heads
*)CNIL
},
array_str
= {(char *)CNIL
,0,ARRAYSPP
,ARRAY
,5,&array_items
,&array_pages
,&array_name
,(struct heads
*)CNIL
},
sdot_str
= {(char *)CNIL
,0,SDOTSPP
,SDOT
,2,&sdot_items
,&sdot_pages
,&sdot_name
,(struct heads
*)CNIL
},
val_str
= {(char *)CNIL
,0,VALSPP
,VALUE
,1,&val_items
,&val_pages
,&val_name
,(struct heads
*)CNIL
},
funct_str
= {(char *)CNIL
,0,BCDSPP
,BCD
,2,&funct_items
,&funct_pages
,&funct_name
,(struct heads
*)CNIL
};
extern int initflag
; /* starts off TRUE: initially gc not allowed */
int gcflag
= FALSE
; /* TRUE during garbage collection */
int current
= 0; /* number of pages currently allocated */
static struct types
*(spaces
[NUMSPACES
]) =
{&atom_str
, &strng_str
, &int_str
,
&dtpr_str
, &doub_str
, &array_str
,
&sdot_str
, &val_str
, &funct_str
};
/** get_more_space(type_struct) *****************************************/
/* Allocates and structures a new page, returning 0. */
/* If no space is available, returns 1. */
get_more_space(type_struct
)
struct types
*type_struct
;
/* mustn't look at plist of plima too soon */
while( plim
=copval(plima
,(lispval
)CNIL
), TYPE(plim
)!=INT
)
copval(plima
,error("BAD PAGE LIMIT",TRUE
));
if( plim
->i
<= current
) return(1); /* Can't allocate */
if( current
>= TTSIZE
) return(2);
/* bump the page counter for this space */
++((*(type_struct
->pages
))->i
);
SETTYPE(start
, type_struct
->type
); /* set type of page */
type_struct
->space_left
= type_struct
->space
;
next
= &header
[ current
++ ];
if ((type_struct
->type
)==STRNG
)
type_struct
->next_free
= start
;
return(0); /* space was available */
next
->link
= type_struct
->first
;
type_struct
->first
= next
;
temp
= loop
= (int *) start
;
for(cntr
=1; cntr
< type_struct
->space
; cntr
++)
loop
= (int *) (*loop
= (int) (loop
+ type_struct
->type_len
));
*loop
= (int) (type_struct
->next_free
);
type_struct
->next_free
= (char *) temp
;
/* if type atom, set pnames to CNIL */
if( type_struct
== &atom_str
)
for(cntr
=0, p
=(lispval
) temp
; cntr
<atom_str
.space
; ++cntr
)
p
->pname
= (char *) CNIL
;
p
= (lispval
) ((int *)p
+ atom_str
.type_len
);
return(0); /* space was available */
/** next_one(type_struct) ************************************************/
/* Allocates one new item of each kind of space, except STRNG. */
/* If there is no space, calls gc, the garbage collector. */
/* If there is still no space, allocates a new page using */
/* get_more_space(type_struct) */
struct types
*type_struct
;
while(type_struct
->next_free
== (char *) CNIL
)
if((type_struct
->type
!= ATOM
) && /* can't collect atoms */
(type_struct
->type
!= STRNG
) && /* can't collect strings */
(gcthresh
->i
<= current
) && /* threshhold for gc */
ISNIL(copval(gcdis
,CNIL
)) && /* gc not disabled */
(NOTNIL(copval(gcload
,CNIL
)) || (loading
->clb
!= tatom
)) &&
/* not to collect during load */
(initflag
== FALSE
) && /* dont gc during init */
(gcflag
== FALSE
)) /* don't recurse gc */
/* fputs("Collecting",poport);
gc(type_struct
); /* collect */
if( type_struct
->next_free
!= (char *) CNIL
) break;
if(! (g
=get_more_space(type_struct
))) break;
plimit
->i
= current
+NUMSPACES
;
/* allow a few more pages */
copval(plima
,plimit
); /* restore to reserved reg */
error("PAGE LIMIT EXCEEDED--EMERGENCY PAGES ALLOCATED",
else error("SORRY, ABSOLUTE PAGE LIMIT HAS BEEN REACHED",
temp
= type_struct
->next_free
;
type_struct
->next_free
= * (char **)(type_struct
->next_free
);
return(next_one(&int_str
));
temp
= next_one(&dtpr_str
);
temp
->car
= temp
->cdr
= nil
;
return(next_one(&doub_str
));
temp
= next_one(&sdot_str
);
temp
->car
= temp
->cdr
= 0;
save
= (struct atom
*) next_one(&atom_str
) ;
save
->plist
= save
->fnbnd
= nil
;
save
->hshlnk
= (struct atom
*)CNIL
;
atmlen
= strlen(strbuf
)+1;
if(atmlen
> strng_str
.space_left
)
while(get_more_space(&strng_str
))
error("YOU HAVE RUN OUT OF SPACE",TRUE
);
strcpy((save
= strng_str
.next_free
), strbuf
);
while(atmlen2
% 4) ++atmlen2
; /* even up length of string */
strng_str
.next_free
+= atmlen2
;
strng_str
.space_left
-= atmlen2
;
char *inewstr(s
) char *s
;
strbuf
[STRBLEN
-1] = '\0';
strcpyn(strbuf
,s
,STRBLEN
-1);
temp
= next_one(&array_str
);
temp
->data
= (char *)nil
;
{ error("BAD FUNCTION DESCRIPTOR USED IN CALL",FALSE
); }
temp
= next_one(&funct_str
);
temp
= next_one(&val_str
);
inewval(arg
) lispval arg
;
temp
= next_one(&val_str
);
/** Ngc *****************************************************************/
/* LISP interface to gc. */
if( ISNIL(lbot
->val
) ) return(gc(CNIL
));
if( TYPE(lbot
->val
) != DTPR
) error("BAD CALL TO GC",FALSE
);
if( NOTNIL(lbot
->val
->car
) )
temp
= eval(lbot
->val
->car
);
if( TYPE(temp
) == PORT
) chkport
= (FILE *)*temp
;
/** gc(type_struct) *****************************************************/
/* garbage collector: Collects garbage by mark and sweep algorithm. */
/* After this is done, calls the Nlambda, gcafter. */
/* gc may also be called from LISP, as a lambda of no arguments. */
struct types
*type_struct
;
save
= copval(gcport
,CNIL
);
while( (TYPE(save
) != PORT
) && NOTNIL(save
))
save
= error("NEED PORT FOR GC",TRUE
);
chkport
= ISNIL(save
) ? poport
: (FILE *)*save
;
gc1(NOTNIL(copval(gccheck
,CNIL
)) || (chkport
!=poport
)); /* mark&sweep */
/* Now we call gcafter--special case if gc called from LISP */
if( type_struct
== (struct types
*) CNIL
)
gccall1
->cdr
= nil
; /* make the call "(gcafter)" */
gccall2
->car
= *(type_struct
->type_name
);
gcflag
= TRUE
; /* flag to indicate in garbage collector */
save
= eval(gccall1
); /* call gcafter */
gcflag
= FALSE
; /* turn off flag */
GCtime
+= (finish
.mytime
- begin
.mytime
);
return(save
); /* return result of gcafter */
/* gc1() **************************************************************/
/* Mark-and-sweep phase */
gc1(chkflag
) int chkflag
;
register int *start
, *point
;
/* decide whether to check LISP structure or not */
/* first set all bit maps to zero */
for(i
=0; i
<((int)datalim
>> 8); ++i
) bitmapq
[i
] = zeroq
;
/* then mark all atoms' plists, clbs, and function bindings */
for(loop
=atom_str
.first
; loop
!=(struct heads
*)CNIL
; loop
=loop
->link
)
for(start
=(int *)(loop
->pntr
), i
=1;
start
= start
+ atom_str
.type_len
, ++i
)
/* unused atoms are marked with pname == CNIL */
/* this is done by get_more_space, as well as */
/* by gc (in the future) */
if(((lispval
)start
)->pname
== (char *)CNIL
) continue;
#define MARKSUB(p) if(nil!=((lispval)start)->p)markdp(((lispval)start)->p);
/* next run up the name stack */
for(loop2
= np
- 1; loop2
>= orgnp
; --loop2
) markdp((loop2
->val
));
/* next mark all compiler linked data */
while((start
= point
) != (int *)CNIL
) {
point
= (int *)*(point
-1);
/* next mark all system-significant lisp data */
for(i
=0; i
<SIGNIF
; ++i
) markdp((lispsys
[i
]));
/* all accessible data has now been marked. */
/* all collectable spaces must be swept, */
/* and freelists constructed. */
for(i
=0; i
<NUMSPACES
; ++i
)
/* STRINGS do not participate. */
/* ATOMS dont either (currently) */
if((typep
==STRNG
) || (typep
==ATOM
)) continue;
s
->space_left
= 0; /* we will count free cells */
(*(s
->items
))->i
= 0; /* and compute cells used */
/* for each space, traverse list of pages. */
s
->next_free
= (char *) CNIL
; /* reinitialize free list */
for(loop
= s
->first
; loop
!= (struct heads
*) CNIL
; loop
=loop
->link
)
/* add another page's worth to use count */
(*(s
->items
))->i
+= s
->space
;
/* for each page, make a list of unmarked data */
for(j
=0, point
=(int *)(loop
->pntr
);
j
<s
->space
; ++j
, point
+= s
->type_len
)
/* update pointer to free list*/
/* update count of free list */
*point
= (int)(s
->next_free
);
s
->next_free
= (char *) point
;
(*(s
->items
))->i
-= s
->space_left
; /* compute cells used */
/** alloc() *************************************************************/
/* This routine tries to allocate one more page of the space named */
/* by the argument. If no more space is available returns 1, else 0. */
lispval tname
; int npages
;
for( jj
=0; jj
<npages
; ++jj
)
if(get_more_space(spaces
[ii
])) break;
lispval tname
; int nitems
;
nitems
= nitems
*4*spaces
[ii
]->type_len
; /* find c-length of space */
while( nitems
%512 ) ++nitems
; /* round up to right length */
error("NOT ENOUGH SPACE FOR ARRAY",FALSE
);
(datalim
= (lispval
)(charadd
+nitems
));
if((((int)datalim
) >> 9) > TTSIZE
) {
datalim
= (lispval
) (TTSIZE
<< 9);
for(jj
=0; jj
<nitems
; jj
=jj
+512) {
SETTYPE(charadd
+jj
, spaces
[ii
]->type
);
return((lispval
)charadd
);
int csizeof(tname
) lispval tname
;
return( spaces
[typenum(tname
)]->type_len
* 4 );
int typenum(tname
) lispval tname
;
chek
: for(ii
=0; ii
<NUMSPACES
; ++ii
)
if(tname
== *(spaces
[ii
]->type_name
)) break;
tname
= error("BAD TYPE NAME",TRUE
);
/** markit(p) ***********************************************************/
markit(p
) lispval
*p
; { markdp(*p
); }
/** markdp(p) ***********************************************************/
/* markdp is the routine which marks each data item. If it is a */
/* dotted pair, the car and cdr are marked also. */
/* An iterative method is used to mark list structure, to avoid */
/* excessive recursion. */
markdp(p
) register lispval p
;
/* register int r, s; (goes with non-asm readbit, oksetbit) */
if((int)p
<= 0) return; /* do not mark special data types or nil=0 */
ftstbit
; /* mark array itself */
markdp(p
->accfun
); /* mark access function */
markdp(p
->aux
); /* mark aux data */
markdp(p
->length
); /* mark length */
markdp(p
->delta
); /* mark delta */
register int i
, l
; int d
;
register char *dataptr
= p
->data
;
for(i
=0, l
=p
->length
->i
, d
=p
->delta
->i
; i
<l
; ++i
)
static char *xx
; /* pointer to next available blank page */
static int cycle
= 0; /* number of blank pages available */
lispval u
; /* used to compute limits of bit table */
xx
= sbrk(16*NBPG
); /* get pages 16 at a time */
lispend("For sbrk from lisp: no space... Goodbye!");
done
: if( (u
= (lispval
)(xx
+NBPG
)) > datalim
) datalim
= u
;
char *ysbrk(pages
,type
) int pages
, type
;
char *xx
; /* will point to block of storage */
error("OUT OF SPACE FOR ARRAY REQUEST",FALSE
);
datalim
= (lispval
)(xx
+pages
*NBPG
); /* compute bit table limit */
for(i
= 0; i
< pages
; ++i
) {
SETTYPE((xx
+ i
*NBPG
),type
);
return(xx
); /* return pointer to block of storage */
/* getatom **************************************************************/
/* returns either an existing atom with the name specified in strbuf, or*/
/* if the atom does not already exist, regurgitates a new one and */
register char *name
, *endname
;
if (*name
== (char)0377) return (eofa
);
for(name
=strbuf
; *name
;) {
hash
&= 0177; /* make sure no high-order bits have crept in */
atmlen
= name
- strbuf
+ 1;
aptr
= (lispval
) hasht
[hash
];
if (strcmp(strbuf
,aptr
->pname
)==0)
aptr
= (lispval
) aptr
->hshlnk
;
aptr
= (lispval
) newatom();
aptr
->hshlnk
= hasht
[hash
];
hasht
[hash
] = (struct atom
*) aptr
;
if ((atmlen
!= 4) && (*name
== 'c') && (*endname
== 'r'))
if((c
= *name
) == 'a') b
->car
= cara
;
else if (c
== 'd') b
->car
= cdra
;