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 genhashtable * 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;
211 /* Update active tasks */
213 struct genpointerlist * ptr=activetasks->list;
215 struct taskparamdescriptor *tpd=ptr->src;
217 for(i=0;i<tpd->numParameters;i++) {
218 void * orig=tpd->parameterArray[i];
220 if (gc_createcopy(orig, ©))
222 tpd->parameterArray[i]=copy;
226 genrehash(activetasks);
229 /* Update failed tasks */
231 struct genpointerlist * ptr=failedtasks->list;
233 struct taskparamdescriptor *tpd=ptr->src;
235 for(i=0;i<tpd->numParameters;i++) {
236 void * orig=tpd->parameterArray[i];
238 if (gc_createcopy(orig, ©))
240 tpd->parameterArray[i]=copy;
244 genrehash(failedtasks);
249 void * ptr=dequeue();
250 void *cpy=((void **)ptr)[1];
251 int type=((int *)cpy)[0];
252 int * pointer=pointerarray[type];
254 /* Array of primitives */
256 } else if (((int)pointer)==1) {
257 /* Array of pointers */
258 struct ArrayObject *ao=(struct ArrayObject *) ptr;
259 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
260 int length=ao->___length___;
262 for(i=0;i<length;i++) {
263 void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
265 if (gc_createcopy(objptr, ©))
267 ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=copy;
272 for(i=1;i<=size;i++) {
273 int offset=pointer[i];
274 void * objptr=*((void **)(((int)ptr)+offset));
276 if (gc_createcopy(objptr, ©))
278 *((void **) (((int)cpy)+offset))=copy;
284 pthread_mutex_unlock(&gclistlock);
288 void * curr_heapbase=0;
289 void * curr_heapptr=0;
290 void * curr_heapgcpoint=0;
291 void * curr_heaptop=0;
293 void * to_heapbase=0;
298 void * tomalloc(int size) {
299 void * ptr=to_heapptr;
308 void checkcollect(void * ptr) {
310 struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
311 pthread_mutex_lock(&gclock); // Wait for GC
313 pthread_mutex_unlock(&gclock);
318 struct listitem * stopforgc(struct garbagelist * ptr) {
319 struct listitem * litem=malloc(sizeof(struct listitem));
321 litem->locklist=pthread_getspecific(threadlocks);
323 pthread_mutex_lock(&gclistlock);
329 pthread_cond_signal(&gccond);
330 pthread_mutex_unlock(&gclistlock);
334 void restartaftergc(struct listitem * litem) {
335 pthread_mutex_lock(&gclistlock);
336 pthread_setspecific(threadlocks, litem->locklist);
337 if (litem->prev==NULL) {
340 litem->prev->next=litem->next;
342 if (litem->next!=NULL) {
343 litem->next->prev=litem->prev;
346 pthread_mutex_unlock(&gclistlock);
351 void * mygcmalloc(struct garbagelist * stackptr, int size) {
354 if (pthread_mutex_trylock(&gclock)!=0) {
355 struct listitem *tmp=stopforgc(stackptr);
356 pthread_mutex_lock(&gclock);
364 if (curr_heapptr>curr_heapgcpoint) {
365 if (curr_heapbase==0) {
366 /* Need to allocate base heap */
367 curr_heapbase=malloc(INITIALHEAPSIZE);
368 bzero(curr_heapbase, INITIALHEAPSIZE);
369 curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
370 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
371 curr_heapptr=curr_heapbase+size;
373 to_heapbase=malloc(INITIALHEAPSIZE);
374 to_heaptop=to_heapbase+INITIALHEAPSIZE;
375 to_heapptr=to_heapbase;
378 pthread_mutex_unlock(&gclock);
383 /* Grow the to heap if necessary */
385 int curr_heapsize=curr_heaptop-curr_heapbase;
386 int to_heapsize=to_heaptop-to_heapbase;
389 last_heapsize=HEAPSIZE(lastgcsize, size);
390 if ((last_heapsize%4)!=0)
391 last_heapsize+=(4-(last_heapsize%4));
393 if (curr_heapsize>last_heapsize)
394 last_heapsize=curr_heapsize;
395 if (last_heapsize>to_heapsize) {
397 to_heapbase=malloc(last_heapsize);
398 to_heaptop=to_heapbase+last_heapsize;
399 to_heapptr=to_heapbase;
403 /* Do our collection */
406 /* Update stat on previous gc size */
407 lastgcsize=(to_heapptr-to_heapbase)+size;
409 /* Flip to/curr heaps */
411 void * tmp=to_heapbase;
412 to_heapbase=curr_heapbase;
416 to_heaptop=curr_heaptop;
420 curr_heapptr=to_heapptr+size;
421 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
422 to_heapptr=to_heapbase;
424 /* Not enough room :(, redo gc */
425 if (curr_heapptr>curr_heapgcpoint) {
427 pthread_mutex_unlock(&gclock);
429 return mygcmalloc(stackptr, size);
432 bzero(tmp, curr_heaptop-tmp);
434 pthread_mutex_unlock(&gclock);
440 pthread_mutex_unlock(&gclock);
447 int gc_createcopy(void * orig, void ** copy_ptr) {
452 int type=((int *)orig)[0];
454 *copy_ptr=((void **)orig)[1];
456 } if (type<NUMCLASSES) {
457 /* We have a normal object */
458 int size=classsize[type];
459 void *newobj=tomalloc(size);
460 memcpy(newobj, orig, size);
462 ((void **)orig)[1]=newobj;
466 /* We have an array */
467 struct ArrayObject *ao=(struct ArrayObject *)orig;
468 int elementsize=classsize[type];
469 int length=ao->___length___;
470 int size=sizeof(struct ArrayObject)+length*elementsize;
471 void *newobj=tomalloc(size);
472 memcpy(newobj, orig, size);
474 ((void **)orig)[1]=newobj;