3 #include "structdefs.h"
5 #include "SimpleHash.h"
6 #include "GenericHashtable.h"
15 #define INITIALHEAPSIZE 10*1024
16 #define GCPOINT(x) ((int)((x)*0.9))
17 /* This define takes in how full the heap is initially and returns a new heap size to use */
18 #define HEAPSIZE(x,y) (((int)((x)/0.6))+y)
21 extern struct Queue * activetasks;
22 extern struct parameterwrapper * objectqueues[NUMCLASSES];
23 extern struct genhashtable * failedtasks;
24 extern struct RuntimeHash *forward;
25 extern struct RuntimeHash *reverse;
26 extern struct RuntimeHash *fdtoobject;
31 struct listitem * list=NULL;
37 struct pointerblock *next;
40 struct pointerblock *head=NULL;
42 struct pointerblock *tail=NULL;
44 struct pointerblock *spare=NULL;
46 void enqueue(void *ptr) {
47 if (headindex==NUMPTRS) {
48 struct pointerblock * tmp;
53 tmp=malloc(sizeof(struct pointerblock));
58 head->ptrs[headindex++]=ptr;
62 if (tailindex==NUMPTRS) {
63 struct pointerblock *tmp=tail;
71 return tail->ptrs[tailindex++];
75 if ((head==tail)&&(tailindex==headindex))
80 void collect(struct garbagelist * stackptr) {
83 pthread_mutex_lock(&gclistlock);
85 if ((listcount+1)==threadcount) {
86 break; /* Have all other threads stopped */
88 pthread_cond_wait(&gccond, &gclistlock);
95 head=tail=malloc(sizeof(struct pointerblock));
97 /* Check current stack */
100 struct listitem *listptr=list;
101 while(stackptr!=NULL) {
104 while(stackptr!=NULL) {
106 for(i=0;i<stackptr->size;i++) {
107 void * orig=stackptr->array[i];
109 if (gc_createcopy(orig,©))
111 stackptr->array[i]=copy;
113 stackptr=stackptr->next;
116 /* Go to next thread */
118 void * orig=listptr->locklist;
120 if (gc_createcopy(orig,©))
122 listptr->locklist=copy;
123 stackptr=listptr->stackptr;
124 listptr=listptr->next;
132 /* Update objectsets */
134 for(i=0;i<NUMCLASSES;i++) {
135 struct parameterwrapper * p=objectqueues[i];
137 struct RuntimeHash * set=p->objectset;
138 struct RuntimeNode * ptr=set->listhead;
140 void *orig=(void *)ptr->key;
142 if (gc_createcopy(orig, ©))
148 RuntimeHashrehash(set); /* Rehash the table */
155 struct RuntimeNode * ptr=forward->listhead;
157 void * orig=(void *)ptr->key;
159 if (gc_createcopy(orig, ©))
165 RuntimeHashrehash(forward); /* Rehash the table */
169 struct RuntimeNode * ptr=reverse->listhead;
171 void *orig=(void *)ptr->data;
173 if (gc_createcopy(orig, ©))
182 struct RuntimeNode * ptr=fdtoobject->listhead;
184 void *orig=(void *)ptr->data;
186 if (gc_createcopy(orig, ©))
196 /* Update active tasks */
197 struct QueueItem * ptr=activetasks->head;
199 struct taskparamdescriptor *tpd=ptr->objectptr;
201 for(i=0;i<tpd->numParameters;i++) {
202 void *orig=tpd->parameterArray[i];
204 if (gc_createcopy(orig, ©))
206 tpd->parameterArray[i]=copy;
211 /* Update failed tasks */
213 struct genpointerlist * ptr=failedtasks->list;
215 struct taskparamdescriptor *tpd=ptr->src;
219 for(i=0;i<tpd->numParameters;i++) {
220 orig=tpd->parameterArray[i];
221 if (gc_createcopy(orig, ©))
223 tpd->parameterArray[i]=copy;
227 genrehash(failedtasks);
232 void * ptr=dequeue();
233 void *cpy=((void **)ptr)[1];
234 int type=((int *)cpy)[0];
235 int * pointer=pointerarray[type];
237 /* Array of primitives */
239 } else if (((int)pointer)==1) {
240 /* Array of pointers */
241 struct ArrayObject *ao=(struct ArrayObject *) ptr;
242 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
243 int length=ao->___length___;
245 for(i=0;i<length;i++) {
246 void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
248 if (gc_createcopy(objptr, ©))
250 ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=copy;
255 for(i=1;i<=size;i++) {
256 int offset=pointer[i];
257 void * objptr=*((void **)(((int)ptr)+offset));
259 if (gc_createcopy(objptr, ©))
261 *((void **) (((int)cpy)+offset))=copy;
267 pthread_mutex_unlock(&gclistlock);
271 void * curr_heapbase=0;
272 void * curr_heapptr=0;
273 void * curr_heapgcpoint=0;
274 void * curr_heaptop=0;
276 void * to_heapbase=0;
281 void * tomalloc(int size) {
282 void * ptr=to_heapptr;
291 void checkcollect(void * ptr) {
293 struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
294 pthread_mutex_lock(&gclock); // Wait for GC
296 pthread_mutex_unlock(&gclock);
301 struct listitem * stopforgc(struct garbagelist * ptr) {
302 struct listitem * litem=malloc(sizeof(struct listitem));
304 litem->locklist=pthread_getspecific(threadlocks);
306 pthread_mutex_lock(&gclistlock);
312 pthread_cond_signal(&gccond);
313 pthread_mutex_unlock(&gclistlock);
317 void restartaftergc(struct listitem * litem) {
318 pthread_mutex_lock(&gclistlock);
319 pthread_setspecific(threadlocks, litem->locklist);
320 if (litem->prev==NULL) {
323 litem->prev->next=litem->next;
325 if (litem->next!=NULL) {
326 litem->next->prev=litem->prev;
329 pthread_mutex_unlock(&gclistlock);
334 void * mygcmalloc(struct garbagelist * stackptr, int size) {
337 if (pthread_mutex_trylock(&gclock)!=0) {
338 struct listitem *tmp=stopforgc(stackptr);
339 pthread_mutex_lock(&gclock);
347 if (curr_heapptr>curr_heapgcpoint) {
348 if (curr_heapbase==0) {
349 /* Need to allocate base heap */
350 curr_heapbase=malloc(INITIALHEAPSIZE);
351 bzero(curr_heapbase, INITIALHEAPSIZE);
352 curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
353 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
354 curr_heapptr=curr_heapbase+size;
356 to_heapbase=malloc(INITIALHEAPSIZE);
357 to_heaptop=to_heapbase+INITIALHEAPSIZE;
358 to_heapptr=to_heapbase;
361 pthread_mutex_unlock(&gclock);
366 /* Grow the to heap if necessary */
368 int curr_heapsize=curr_heaptop-curr_heapbase;
369 int to_heapsize=to_heaptop-to_heapbase;
372 last_heapsize=HEAPSIZE(lastgcsize, size);
373 if ((last_heapsize%4)!=0)
374 last_heapsize+=(4-(last_heapsize%4));
376 if (curr_heapsize>last_heapsize)
377 last_heapsize=curr_heapsize;
378 if (last_heapsize>to_heapsize) {
380 to_heapbase=malloc(last_heapsize);
381 to_heaptop=to_heapbase+last_heapsize;
382 to_heapptr=to_heapbase;
386 /* Do our collection */
389 /* Update stat on previous gc size */
390 lastgcsize=(to_heapptr-to_heapbase)+size;
392 /* Flip to/curr heaps */
394 void * tmp=to_heapbase;
395 to_heapbase=curr_heapbase;
399 to_heaptop=curr_heaptop;
403 curr_heapptr=to_heapptr+size;
404 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
405 to_heapptr=to_heapbase;
407 /* Not enough room :(, redo gc */
408 if (curr_heapptr>curr_heapgcpoint) {
410 pthread_mutex_unlock(&gclock);
412 return mygcmalloc(stackptr, size);
415 bzero(tmp, curr_heaptop-tmp);
417 pthread_mutex_unlock(&gclock);
423 pthread_mutex_unlock(&gclock);
430 int gc_createcopy(void * orig, void ** copy_ptr) {
435 int type=((int *)orig)[0];
437 *copy_ptr=((void **)orig)[1];
439 } if (type<NUMCLASSES) {
440 /* We have a normal object */
441 int size=classsize[type];
442 void *newobj=tomalloc(size);
443 memcpy(newobj, orig, size);
445 ((void **)orig)[1]=newobj;
449 /* We have an array */
450 struct ArrayObject *ao=(struct ArrayObject *)orig;
451 int elementsize=classsize[type];
452 int length=ao->___length___;
453 int size=sizeof(struct ArrayObject)+length*elementsize;
454 void *newobj=tomalloc(size);
455 memcpy(newobj, orig, size);
457 ((void **)orig)[1]=newobj;