3 #include "structdefs.h"
5 #include "SimpleHash.h"
6 #include "GenericHashtable.h"
18 #define INITIALHEAPSIZE 10*1024
19 #define GCPOINT(x) ((int)((x)*0.9))
20 /* This define takes in how full the heap is initially and returns a new heap size to use */
21 #define HEAPSIZE(x,y) (((int)((x)/0.6))+y)
24 extern struct Queue * activetasks;
25 extern struct parameterwrapper * objectqueues[NUMCLASSES];
26 extern struct genhashtable * failedtasks;
27 extern struct taskparamdescriptor *currtpd;
28 extern struct RuntimeHash *forward;
29 extern struct RuntimeHash *reverse;
30 extern struct RuntimeHash *fdtoobject;
35 struct listitem * list=NULL;
41 struct pointerblock *next;
44 struct pointerblock *head=NULL;
46 struct pointerblock *tail=NULL;
48 struct pointerblock *spare=NULL;
50 void enqueue(void *ptr) {
51 if (headindex==NUMPTRS) {
52 struct pointerblock * tmp;
57 tmp=malloc(sizeof(struct pointerblock));
62 head->ptrs[headindex++]=ptr;
66 if (tailindex==NUMPTRS) {
67 struct pointerblock *tmp=tail;
75 return tail->ptrs[tailindex++];
79 if ((head==tail)&&(tailindex==headindex))
84 void collect(struct garbagelist * stackptr) {
87 pthread_mutex_lock(&gclistlock);
89 if ((listcount+1)==threadcount) {
90 break; /* Have all other threads stopped */
92 pthread_cond_wait(&gccond, &gclistlock);
99 head=tail=malloc(sizeof(struct pointerblock));
101 /* Check current stack */
104 struct listitem *listptr=list;
105 while(stackptr!=NULL) {
108 while(stackptr!=NULL) {
110 for(i=0;i<stackptr->size;i++) {
111 void * orig=stackptr->array[i];
113 if (gc_createcopy(orig,©))
115 stackptr->array[i]=copy;
117 stackptr=stackptr->next;
120 /* Go to next thread */
122 void * orig=listptr->locklist;
124 if (gc_createcopy(orig,©))
126 listptr->locklist=copy;
127 stackptr=listptr->stackptr;
128 listptr=listptr->next;
136 /* Update objectsets */
138 for(i=0;i<NUMCLASSES;i++) {
139 struct parameterwrapper * p=objectqueues[i];
141 struct RuntimeHash * set=p->objectset;
142 struct RuntimeNode * ptr=set->listhead;
144 void *orig=(void *)ptr->key;
146 if (gc_createcopy(orig, ©))
152 RuntimeHashrehash(set); /* Rehash the table */
159 struct RuntimeNode * ptr=forward->listhead;
161 void * orig=(void *)ptr->key;
163 if (gc_createcopy(orig, ©))
169 RuntimeHashrehash(forward); /* Rehash the table */
173 struct RuntimeNode * ptr=reverse->listhead;
175 void *orig=(void *)ptr->data;
177 if (gc_createcopy(orig, ©))
186 struct RuntimeNode * ptr=fdtoobject->listhead;
188 void *orig=(void *)ptr->data;
190 if (gc_createcopy(orig, ©))
199 /* Update current task descriptor */
201 for(i=0;i<currtpd->numParameters;i++) {
202 void *orig=currtpd->parameterArray[i];
204 if (gc_createcopy(orig, ©))
206 currtpd->parameterArray[i]=copy;
212 /* Update active tasks */
213 struct QueueItem * ptr=activetasks->head;
215 struct taskparamdescriptor *tpd=ptr->objectptr;
217 for(i=0;i<tpd->numParameters;i++) {
218 void *orig=tpd->parameterArray[i];
220 if (gc_createcopy(orig, ©))
222 tpd->parameterArray[i]=copy;
227 /* Update failed tasks */
229 struct genpointerlist * ptr=failedtasks->list;
231 struct taskparamdescriptor *tpd=ptr->src;
233 for(i=0;i<tpd->numParameters;i++) {
234 void * orig=tpd->parameterArray[i];
236 if (gc_createcopy(orig, ©))
238 tpd->parameterArray[i]=copy;
242 genrehash(failedtasks);
247 void * ptr=dequeue();
248 void *cpy=((void **)ptr)[1];
249 int type=((int *)cpy)[0];
250 int * pointer=pointerarray[type];
252 /* Array of primitives */
254 } else if (((int)pointer)==1) {
255 /* Array of pointers */
256 struct ArrayObject *ao=(struct ArrayObject *) ptr;
257 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
258 int length=ao->___length___;
260 for(i=0;i<length;i++) {
261 void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
263 if (gc_createcopy(objptr, ©))
265 ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=copy;
270 for(i=1;i<=size;i++) {
271 int offset=pointer[i];
272 void * objptr=*((void **)(((int)ptr)+offset));
274 if (gc_createcopy(objptr, ©))
276 *((void **) (((int)cpy)+offset))=copy;
282 pthread_mutex_unlock(&gclistlock);
286 void * curr_heapbase=0;
287 void * curr_heapptr=0;
288 void * curr_heapgcpoint=0;
289 void * curr_heaptop=0;
291 void * to_heapbase=0;
296 void * tomalloc(int size) {
297 void * ptr=to_heapptr;
306 void checkcollect(void * ptr) {
308 struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
309 pthread_mutex_lock(&gclock); // Wait for GC
311 pthread_mutex_unlock(&gclock);
316 struct listitem * stopforgc(struct garbagelist * ptr) {
317 struct listitem * litem=malloc(sizeof(struct listitem));
319 litem->locklist=pthread_getspecific(threadlocks);
321 pthread_mutex_lock(&gclistlock);
327 pthread_cond_signal(&gccond);
328 pthread_mutex_unlock(&gclistlock);
332 void restartaftergc(struct listitem * litem) {
333 pthread_mutex_lock(&gclistlock);
334 pthread_setspecific(threadlocks, litem->locklist);
335 if (litem->prev==NULL) {
338 litem->prev->next=litem->next;
340 if (litem->next!=NULL) {
341 litem->next->prev=litem->prev;
344 pthread_mutex_unlock(&gclistlock);
349 void * mygcmalloc(struct garbagelist * stackptr, int size) {
352 if (pthread_mutex_trylock(&gclock)!=0) {
353 struct listitem *tmp=stopforgc(stackptr);
354 pthread_mutex_lock(&gclock);
362 if (curr_heapptr>curr_heapgcpoint) {
363 if (curr_heapbase==0) {
364 /* Need to allocate base heap */
365 curr_heapbase=malloc(INITIALHEAPSIZE);
366 bzero(curr_heapbase, INITIALHEAPSIZE);
367 curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
368 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
369 curr_heapptr=curr_heapbase+size;
371 to_heapbase=malloc(INITIALHEAPSIZE);
372 to_heaptop=to_heapbase+INITIALHEAPSIZE;
373 to_heapptr=to_heapbase;
376 pthread_mutex_unlock(&gclock);
381 /* Grow the to heap if necessary */
383 int curr_heapsize=curr_heaptop-curr_heapbase;
384 int to_heapsize=to_heaptop-to_heapbase;
387 last_heapsize=HEAPSIZE(lastgcsize, size);
388 if ((last_heapsize%4)!=0)
389 last_heapsize+=(4-(last_heapsize%4));
391 if (curr_heapsize>last_heapsize)
392 last_heapsize=curr_heapsize;
393 if (last_heapsize>to_heapsize) {
395 to_heapbase=malloc(last_heapsize);
396 to_heaptop=to_heapbase+last_heapsize;
397 to_heapptr=to_heapbase;
401 /* Do our collection */
404 /* Update stat on previous gc size */
405 lastgcsize=(to_heapptr-to_heapbase)+size;
407 /* Flip to/curr heaps */
409 void * tmp=to_heapbase;
410 to_heapbase=curr_heapbase;
414 to_heaptop=curr_heaptop;
418 curr_heapptr=to_heapptr+size;
419 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
420 to_heapptr=to_heapbase;
422 /* Not enough room :(, redo gc */
423 if (curr_heapptr>curr_heapgcpoint) {
425 pthread_mutex_unlock(&gclock);
427 return mygcmalloc(stackptr, size);
430 bzero(tmp, curr_heaptop-tmp);
432 pthread_mutex_unlock(&gclock);
438 pthread_mutex_unlock(&gclock);
445 int gc_createcopy(void * orig, void ** copy_ptr) {
450 int type=((int *)orig)[0];
452 *copy_ptr=((void **)orig)[1];
454 } if (type<NUMCLASSES) {
455 /* We have a normal object */
456 int size=classsize[type];
457 void *newobj=tomalloc(size);
458 memcpy(newobj, orig, size);
460 ((void **)orig)[1]=newobj;
464 /* We have an array */
465 struct ArrayObject *ao=(struct ArrayObject *)orig;
466 int elementsize=classsize[type];
467 int length=ao->___length___;
468 int size=sizeof(struct ArrayObject)+length*elementsize;
469 void *newobj=tomalloc(size);
470 memcpy(newobj, orig, size);
472 ((void **)orig)[1]=newobj;