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 RuntimeHash *forward;
28 extern struct RuntimeHash *reverse;
29 extern struct RuntimeHash *fdtoobject;
34 struct listitem * list=NULL;
40 struct pointerblock *next;
43 struct pointerblock *head=NULL;
45 struct pointerblock *tail=NULL;
47 struct pointerblock *spare=NULL;
49 void enqueue(void *ptr) {
50 if (headindex==NUMPTRS) {
51 struct pointerblock * tmp;
56 tmp=malloc(sizeof(struct pointerblock));
61 head->ptrs[headindex++]=ptr;
65 if (tailindex==NUMPTRS) {
66 struct pointerblock *tmp=tail;
74 return tail->ptrs[tailindex++];
78 if ((head==tail)&&(tailindex==headindex))
83 void collect(struct garbagelist * stackptr) {
86 pthread_mutex_lock(&gclistlock);
88 if ((listcount+1)==threadcount) {
89 break; /* Have all other threads stopped */
91 pthread_cond_wait(&gccond, &gclistlock);
98 head=tail=malloc(sizeof(struct pointerblock));
100 /* Check current stack */
103 struct listitem *listptr=list;
104 while(stackptr!=NULL) {
107 while(stackptr!=NULL) {
109 for(i=0;i<stackptr->size;i++) {
110 void * orig=stackptr->array[i];
112 if (gc_createcopy(orig,©))
114 stackptr->array[i]=copy;
116 stackptr=stackptr->next;
119 /* Go to next thread */
121 void * orig=listptr->locklist;
123 if (gc_createcopy(orig,©))
125 listptr->locklist=copy;
126 stackptr=listptr->stackptr;
127 listptr=listptr->next;
135 /* Update objectsets */
137 for(i=0;i<NUMCLASSES;i++) {
138 struct parameterwrapper * p=objectqueues[i];
140 struct RuntimeHash * set=p->objectset;
141 struct RuntimeNode * ptr=set->listhead;
143 void *orig=(void *)ptr->key;
145 if (gc_createcopy(orig, ©))
151 RuntimeHashrehash(set); /* Rehash the table */
158 struct RuntimeNode * ptr=forward->listhead;
160 void * orig=(void *)ptr->key;
162 if (gc_createcopy(orig, ©))
168 RuntimeHashrehash(forward); /* Rehash the table */
172 struct RuntimeNode * ptr=reverse->listhead;
174 void *orig=(void *)ptr->data;
176 if (gc_createcopy(orig, ©))
185 struct RuntimeNode * ptr=fdtoobject->listhead;
187 void *orig=(void *)ptr->data;
189 if (gc_createcopy(orig, ©))
199 /* Update active tasks */
200 struct QueueItem * ptr=activetasks->head;
202 struct taskparamdescriptor *tpd=ptr->objectptr;
204 for(i=0;i<tpd->numParameters;i++) {
205 void *orig=tpd->parameterArray[i];
207 if (gc_createcopy(orig, ©))
209 tpd->parameterArray[i]=copy;
214 /* Update failed tasks */
216 struct genpointerlist * ptr=failedtasks->list;
218 struct taskparamdescriptor *tpd=ptr->src;
222 for(i=0;i<tpd->numParameters;i++) {
223 orig=tpd->parameterArray[i];
224 if (gc_createcopy(orig, ©))
226 tpd->parameterArray[i]=copy;
230 genrehash(failedtasks);
235 void * ptr=dequeue();
236 void *cpy=((void **)ptr)[1];
237 int type=((int *)cpy)[0];
238 int * pointer=pointerarray[type];
240 /* Array of primitives */
242 } else if (((int)pointer)==1) {
243 /* Array of pointers */
244 struct ArrayObject *ao=(struct ArrayObject *) ptr;
245 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
246 int length=ao->___length___;
248 for(i=0;i<length;i++) {
249 void *objptr=((void **)(((char *)& ao->___length___)+sizeof(int)))[i];
251 if (gc_createcopy(objptr, ©))
253 ((void **)(((char *)& ao_cpy->___length___)+sizeof(int)))[i]=copy;
258 for(i=1;i<=size;i++) {
259 int offset=pointer[i];
260 void * objptr=*((void **)(((int)ptr)+offset));
262 if (gc_createcopy(objptr, ©))
264 *((void **) (((int)cpy)+offset))=copy;
270 pthread_mutex_unlock(&gclistlock);
274 void * curr_heapbase=0;
275 void * curr_heapptr=0;
276 void * curr_heapgcpoint=0;
277 void * curr_heaptop=0;
279 void * to_heapbase=0;
284 void * tomalloc(int size) {
285 void * ptr=to_heapptr;
294 void checkcollect(void * ptr) {
296 struct listitem * tmp=stopforgc((struct garbagelist *)ptr);
297 pthread_mutex_lock(&gclock); // Wait for GC
299 pthread_mutex_unlock(&gclock);
304 struct listitem * stopforgc(struct garbagelist * ptr) {
305 struct listitem * litem=malloc(sizeof(struct listitem));
307 litem->locklist=pthread_getspecific(threadlocks);
309 pthread_mutex_lock(&gclistlock);
315 pthread_cond_signal(&gccond);
316 pthread_mutex_unlock(&gclistlock);
320 void restartaftergc(struct listitem * litem) {
321 pthread_mutex_lock(&gclistlock);
322 pthread_setspecific(threadlocks, litem->locklist);
323 if (litem->prev==NULL) {
326 litem->prev->next=litem->next;
328 if (litem->next!=NULL) {
329 litem->next->prev=litem->prev;
332 pthread_mutex_unlock(&gclistlock);
337 void * mygcmalloc(struct garbagelist * stackptr, int size) {
340 if (pthread_mutex_trylock(&gclock)!=0) {
341 struct listitem *tmp=stopforgc(stackptr);
342 pthread_mutex_lock(&gclock);
350 if (curr_heapptr>curr_heapgcpoint) {
351 if (curr_heapbase==0) {
352 /* Need to allocate base heap */
353 curr_heapbase=malloc(INITIALHEAPSIZE);
354 bzero(curr_heapbase, INITIALHEAPSIZE);
355 curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
356 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
357 curr_heapptr=curr_heapbase+size;
359 to_heapbase=malloc(INITIALHEAPSIZE);
360 to_heaptop=to_heapbase+INITIALHEAPSIZE;
361 to_heapptr=to_heapbase;
364 pthread_mutex_unlock(&gclock);
369 /* Grow the to heap if necessary */
371 int curr_heapsize=curr_heaptop-curr_heapbase;
372 int to_heapsize=to_heaptop-to_heapbase;
375 last_heapsize=HEAPSIZE(lastgcsize, size);
376 if ((last_heapsize%4)!=0)
377 last_heapsize+=(4-(last_heapsize%4));
379 if (curr_heapsize>last_heapsize)
380 last_heapsize=curr_heapsize;
381 if (last_heapsize>to_heapsize) {
383 to_heapbase=malloc(last_heapsize);
384 to_heaptop=to_heapbase+last_heapsize;
385 to_heapptr=to_heapbase;
389 /* Do our collection */
392 /* Update stat on previous gc size */
393 lastgcsize=(to_heapptr-to_heapbase)+size;
395 /* Flip to/curr heaps */
397 void * tmp=to_heapbase;
398 to_heapbase=curr_heapbase;
402 to_heaptop=curr_heaptop;
406 curr_heapptr=to_heapptr+size;
407 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
408 to_heapptr=to_heapbase;
410 /* Not enough room :(, redo gc */
411 if (curr_heapptr>curr_heapgcpoint) {
413 pthread_mutex_unlock(&gclock);
415 return mygcmalloc(stackptr, size);
418 bzero(tmp, curr_heaptop-tmp);
420 pthread_mutex_unlock(&gclock);
426 pthread_mutex_unlock(&gclock);
433 int gc_createcopy(void * orig, void ** copy_ptr) {
438 int type=((int *)orig)[0];
440 *copy_ptr=((void **)orig)[1];
442 } if (type<NUMCLASSES) {
443 /* We have a normal object */
444 int size=classsize[type];
445 void *newobj=tomalloc(size);
446 memcpy(newobj, orig, size);
448 ((void **)orig)[1]=newobj;
452 /* We have an array */
453 struct ArrayObject *ao=(struct ArrayObject *)orig;
454 int elementsize=classsize[type];
455 int length=ao->___length___;
456 int size=sizeof(struct ArrayObject)+length*elementsize;
457 void *newobj=tomalloc(size);
458 memcpy(newobj, orig, size);
460 ((void **)orig)[1]=newobj;