fix sese garbage collection bug calculating offsets to dependent sese pointers
[IRC.git] / Robust / src / Runtime / garbage.c
1 #include "garbage.h"
2 #include "runtime.h"
3 #include "structdefs.h"
4 #include "Queue.h"
5 #include "SimpleHash.h"
6 #include "chash.h"
7 #include "GenericHashtable.h"
8 #include <string.h>
9 #if defined(THREADS) || defined(DSTM) || defined(STM)
10 #include "thread.h"
11 #endif
12 #ifdef MLP
13 #include "workschedule.h"
14 extern struct QI * headqi;
15 extern struct QI * tailqi;
16 #endif
17
18 #ifdef DMALLOC
19 #include "dmalloc.h"
20 #endif
21 #ifdef DSTM
22 #ifdef RECOVERY
23 #include <DSTM/interface_recovery/dstm.h>
24 #else
25 #include <DSTM/interface/dstm.h>
26 #endif
27 #endif
28 #ifdef STM
29 #include "tm.h"
30 #endif
31 #ifdef DELAYCOMP
32 #include "delaycomp.h"
33 #endif
34
35
36 #define NUMPTRS 100
37
38 #define INITIALHEAPSIZE 256*1024*1024L
39 #define GCPOINT(x) ((INTPTR)((x)*0.99))
40 /* This define takes in how full the heap is initially and returns a new heap size to use */
41 #define HEAPSIZE(x,y) ((INTPTR)(x+y))*2
42
43 #ifdef TASK
44 extern struct genhashtable * activetasks;
45 #ifndef MULTICORE
46 extern struct parameterwrapper * objectqueues[NUMCLASSES];
47 #endif
48 extern struct genhashtable * failedtasks;
49 extern struct taskparamdescriptor *currtpd;
50 extern struct ctable *forward;
51 extern struct ctable *reverse;
52 extern struct RuntimeHash *fdtoobject;
53 #endif
54
55 #ifdef GARBAGESTATS
56 #define MAXSTATS 500
57 long garbagearray[MAXSTATS];
58 #endif
59
60 #if defined(THREADS) || defined(DSTM) || defined(STM)||defined(MLP)
61 int needtocollect=0;
62 struct listitem * list=NULL;
63 int listcount=0;
64 #ifndef MAC
65 __thread struct listitem litem;
66 #endif
67 #endif
68
69 #ifdef MLP
70 __thread SESEcommon* seseCommon;
71 #endif
72
73 //Need to check if pointers are transaction pointers
74 //this also catches the special flag value of 1 for local copies
75 #ifdef DSTM
76 #define ENQUEUE(orig, dst) \
77   if ((!(((unsigned int)orig)&0x1))) { \
78     if (orig>=curr_heapbase&&orig<curr_heaptop) { \
79       void *copy; \
80       if (gc_createcopy(orig,&copy)) \
81         enqueue(copy);\
82       dst=copy; \
83     } \
84   }
85 #elif defined(STM)
86 #define ENQUEUE(orig, dst) \
87   if (orig>=curr_heapbase&&orig<curr_heaptop) { \
88     void *copy; \
89     if (gc_createcopy(orig,&copy)) \
90       enqueue(copy);\
91     dst=copy; \
92   }
93 #define SENQUEUE(orig, dst) \
94   { \
95     void *copy; \
96     if (gc_createcopy(orig,&copy)) \
97       enqueue(copy);\
98     dst=copy; \
99   }
100 #elif defined(FASTCHECK)
101 #define ENQUEUE(orig, dst) \
102   if (((unsigned int)orig)!=1) { \
103     void *copy; \
104     if (gc_createcopy(orig,&copy)) \
105       enqueue(copy);\
106     dst=copy; }
107 #else
108 #define ENQUEUE(orig, dst) \
109   if (orig>=curr_heapbase&&orig<curr_heaptop) { \
110      void *copy; \
111      if (gc_createcopy(orig,&copy)) \
112          enqueue(copy); \
113      dst=copy; \
114   }
115 #endif
116
117
118 struct pointerblock {
119   void * ptrs[NUMPTRS];
120   struct pointerblock *next;
121 };
122
123 void * curr_heapbase=0;
124 void * curr_heapptr=0;
125 void * curr_heapgcpoint=0;
126 void * curr_heaptop=0;
127
128 void * to_heapbase=0;
129 void * to_heapptr=0;
130 void * to_heaptop=0;
131 long lastgcsize=0;
132
133
134 struct pointerblock *head=NULL;
135 int headindex=0;
136 struct pointerblock *tail=NULL;
137 int tailindex=0;
138 struct pointerblock *spare=NULL;
139
140 void enqueue(void *ptr) {
141   if (headindex==NUMPTRS) {
142     struct pointerblock * tmp;
143     if (spare!=NULL) {
144       tmp=spare;
145       spare=NULL;
146     } else      tmp=malloc(sizeof(struct pointerblock));
147     head->next=tmp;
148     head=tmp;
149     headindex=0;
150   }
151   head->ptrs[headindex++]=ptr;
152 }
153
154 void * dequeue() {
155   if (tailindex==NUMPTRS) {
156     struct pointerblock *tmp=tail;
157     tail=tail->next;
158     tailindex=0;
159     if (spare!=NULL)
160       free(tmp);
161     else
162       spare=tmp;
163   }
164   return tail->ptrs[tailindex++];
165 }
166
167 #ifdef STM
168 void fixobjlist(struct objlist * ptr) {
169   while(ptr!=NULL) {
170     int i;
171     for(i=0;i<ptr->offset;i++) {
172       SENQUEUE(ptr->objs[i], ptr->objs[i]);
173     }
174     ptr=ptr->next;
175   }
176 }
177
178 void fixtable(chashlistnode_t ** tc_table, chashlistnode_t **tc_list, cliststruct_t **cstr, unsigned int tc_size) {
179   unsigned int mask=(tc_size<<4)-1;
180   chashlistnode_t *node=calloc(tc_size, sizeof(chashlistnode_t));
181   chashlistnode_t *ptr=*tc_table;
182   chashlistnode_t *curr;
183   unsigned int i;
184   unsigned int index;
185   int isfirst;
186   chashlistnode_t *newlist=NULL;
187   for(i=0;i<tc_size;i++) {
188     curr=&ptr[i];
189     isfirst=1;
190     do {                      //Inner loop to go through linked lists
191       void * key;
192       chashlistnode_t *tmp,*next;
193       
194       if ((key=(void *)curr->key) == 0) {             //Exit inner loop if there the first element is 0
195         break;                  //key = val =0 for element if not present within the hash table
196       }
197       SENQUEUE(key, key);
198       if (curr->val>=curr_heapbase&&curr->val<curr_heaptop) {
199         SENQUEUE(curr->val, curr->val);
200       } else {
201         //rewrite transaction cache entry
202         void *vptr=curr->val;
203         int type=((int *)vptr)[0];
204         unsigned INTPTR *pointer=pointerarray[type];
205         if (pointer==0) {
206           //array of primitives - do nothing
207           struct ArrayObject *ao=(struct ArrayObject *) vptr;
208           SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___));
209         } else if (((INTPTR)pointer)==1) {
210           //array of pointers
211           struct ArrayObject *ao=(struct ArrayObject *) vptr;
212           int length=ao->___length___;
213           int i;
214           SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___));
215 #ifdef STMARRAY
216           int lowindex=ao->lowindex;
217           int highindex=ao->highindex;
218           int j;
219           for(j=lowindex; j<=highindex; j++) {
220             unsigned int lockval;
221             GETLOCKVAL(lockval, ao, j);
222             if (lockval!=STMNONE) {
223               int lowi=(j<<INDEXSHIFT)/sizeof(void *);
224               int highi=lowi+(INDEXLENGTH/sizeof(void *));
225               for(i=lowi; i<highi;i++) {
226 #else
227               for(i=0; i<length; i++) {
228 #endif
229                 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
230                 SENQUEUE(objptr, ((void **)(((char *)&ao->___length___)+sizeof(int)))[i]);
231               }
232 #ifdef STMARRAY
233             }
234           }
235 #endif
236         } else {
237           INTPTR size=pointer[0];
238           int i;
239           for(i=1; i<=size; i++) {
240             unsigned int offset=pointer[i];
241             void * objptr=*((void **)(((char *)vptr)+offset));
242             SENQUEUE(objptr, *((void **)(((char *)vptr)+offset)));
243           }
244         }
245       }
246
247       next = curr->next;
248       index = (((unsigned INTPTR)key) & mask) >>4;
249
250       curr->key=key;
251       tmp=&node[index];
252       // Insert into the new table
253       if(tmp->key == 0) {
254         tmp->key = curr->key;
255         tmp->val = curr->val;
256         tmp->lnext=newlist;
257         newlist=tmp;
258       } else if (isfirst) {
259         chashlistnode_t *newnode;
260         if ((*cstr)->num<NUMCLIST) {
261           newnode=&(*cstr)->array[(*cstr)->num];
262           (*cstr)->num++;
263         } else {
264           //get new list
265           cliststruct_t *tcl=calloc(1,sizeof(cliststruct_t));
266           tcl->next=*cstr;
267           *cstr=tcl;
268           newnode=&tcl->array[0];
269           tcl->num=1;
270         }
271         newnode->key = curr->key;
272         newnode->val = curr->val;
273         newnode->next = tmp->next;
274         newnode->lnext=newlist;
275         newlist=newnode;
276         tmp->next=newnode;
277       } else {
278         curr->lnext=newlist;
279         newlist=curr;
280         curr->next=tmp->next;
281         tmp->next=curr;
282       }
283       isfirst = 0;
284       curr = next;
285     } while(curr!=NULL);
286   }
287   free(ptr);
288   (*tc_table)=node;
289   (*tc_list)=newlist;
290 }
291 #endif
292
293 int moreItems() {
294   if ((head==tail)&&(tailindex==headindex))
295     return 0;
296   return 1;
297 }
298
299 #ifdef TASK
300 struct pointerblock *taghead=NULL;
301 int tagindex=0;
302
303 void enqueuetag(struct ___TagDescriptor___ *ptr) {
304   if (tagindex==NUMPTRS) {
305     struct pointerblock * tmp=malloc(sizeof(struct pointerblock));
306     tmp->next=taghead;
307     taghead=tmp;
308     tagindex=0;
309   }
310   taghead->ptrs[tagindex++]=ptr;
311 }
312 #endif
313
314 #if defined(STM)||defined(THREADS)||defined(MLP)
315 __thread char * memorybase=NULL;
316 __thread char * memorytop=NULL;
317 #endif
318
319
320 void collect(struct garbagelist * stackptr) {
321 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
322   needtocollect=1;
323   pthread_mutex_lock(&gclistlock);
324   while(1) {
325     if ((listcount+1)==threadcount) {
326       break; /* Have all other threads stopped */
327     }
328     pthread_cond_wait(&gccond, &gclistlock);
329   }
330 #endif
331 #ifdef DELAYCOMP
332   ptrstack.prev=stackptr;
333   stackptr=(struct garbagelist *) &ptrstack;
334 #if defined(STMARRAY)&&!defined(DUALVIEW)
335   arraystack.prev=stackptr;
336   stackptr=(struct garbagelist *) &arraystack;
337 #endif
338 #endif
339
340 #ifdef GARBAGESTATS
341   {
342     int i;
343     for(i=0;i<MAXSTATS;i++)
344       garbagearray[i]=0;
345   }
346 #endif
347
348   if (head==NULL) {
349     headindex=0;
350     tailindex=0;
351     head=tail=malloc(sizeof(struct pointerblock));
352   }
353
354 #ifdef TASK
355   if (taghead==NULL) {
356     tagindex=0;
357     taghead=malloc(sizeof(struct pointerblock));
358     taghead->next=NULL;
359   }
360 #endif
361
362 #ifdef STM
363   if (c_table!=NULL) {
364     fixtable(&c_table, &c_list, &c_structs, c_size);
365     fixobjlist(newobjs);
366 #ifdef STMSTATS
367     fixobjlist(lockedobjs);
368 #endif
369   }
370 #endif
371 #if defined(STM)||defined(THREADS)||defined(MLP)
372   memorybase=NULL;
373 #endif
374  
375   /* Check current stack */
376 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
377   {
378     struct listitem *listptr=list;
379     while(1) {
380 #endif
381       
382   while(stackptr!=NULL) {
383     int i;
384     for(i=0; i<stackptr->size; i++) {
385       void * orig=stackptr->array[i];
386       ENQUEUE(orig, stackptr->array[i]);
387     }
388     stackptr=stackptr->next;
389   }
390 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
391   /* Go to next thread */
392 #ifndef MAC
393   //skip over us
394   if (listptr==&litem) {
395 #ifdef MLP
396     // update forward list & memory queue for the current SESE
397     updateForwardList(((SESEcommon*)listptr->seseCommon)->forwardList,FALSE);
398     updateMemoryQueue((SESEcommon*)(listptr->seseCommon));
399 #endif
400     listptr=listptr->next;
401   }
402 #else
403  {
404   struct listitem *litem=pthread_getspecific(litemkey);
405   if (listptr==litem) {
406     listptr=listptr->next;
407   }
408  }
409 #endif
410  
411   if (listptr!=NULL) {
412 #ifdef THREADS
413     void * orig=listptr->locklist;
414     ENQUEUE(orig, listptr->locklist);
415 #endif
416 #ifdef STM
417     if ((*listptr->tc_table)!=NULL) {
418       fixtable(listptr->tc_table, listptr->tc_list, listptr->tc_structs, listptr->tc_size);
419       fixobjlist(listptr->objlist);
420 #ifdef STMSTATS
421       fixobjlist(listptr->lockedlist);
422 #endif
423     }
424 #endif
425 #if defined(STM)||defined(THREADS)||defined(MLP)
426     *(listptr->base)=NULL;
427 #endif
428 #ifdef MLP
429     // update forward list & memory queue for all running SESEs.
430     updateForwardList(((SESEcommon*)listptr->seseCommon)->forwardList,FALSE);
431     updateMemoryQueue((SESEcommon*)(listptr->seseCommon));
432 #endif
433     stackptr=listptr->stackptr;
434     listptr=listptr->next;
435   } else
436     break;
437 }
438 }
439 #endif
440
441 #ifdef FASTCHECK
442   ENQUEUE(___fcrevert___, ___fcrevert___);
443 #endif
444
445 #ifdef TASK
446   {
447     /* Update objectsets */
448     int i;
449     for(i=0; i<NUMCLASSES; i++) {
450 #if !defined(MULTICORE)
451       struct parameterwrapper * p=objectqueues[i];
452       while(p!=NULL) {
453         struct ObjectHash * set=p->objectset;
454         struct ObjectNode * ptr=set->listhead;
455         while(ptr!=NULL) {
456           void *orig=(void *)ptr->key;
457           ENQUEUE(orig, *((void **)(&ptr->key)));
458           ptr=ptr->lnext;
459         }
460         ObjectHashrehash(set); /* Rehash the table */
461         p=p->next;
462       }
463 #endif
464     }
465   }
466
467 #ifndef FASTCHECK
468   if (forward!=NULL) {
469     struct cnode * ptr=forward->listhead;
470     while(ptr!=NULL) {
471       void * orig=(void *)ptr->key;
472       ENQUEUE(orig, *((void **)(&ptr->key)));
473       ptr=ptr->lnext;
474     }
475     crehash(forward); /* Rehash the table */
476   }
477
478   if (reverse!=NULL) {
479     struct cnode * ptr=reverse->listhead;
480     while(ptr!=NULL) {
481       void *orig=(void *)ptr->val;
482       ENQUEUE(orig, *((void**)(&ptr->val)));
483       ptr=ptr->lnext;
484     }
485   }
486 #endif
487
488   {
489     struct RuntimeNode * ptr=fdtoobject->listhead;
490     while(ptr!=NULL) {
491       void *orig=(void *)ptr->data;
492       ENQUEUE(orig, *((void**)(&ptr->data)));
493       ptr=ptr->lnext;
494     }
495   }
496
497   {
498     /* Update current task descriptor */
499     int i;
500     for(i=0; i<currtpd->numParameters; i++) {
501       void *orig=currtpd->parameterArray[i];
502       ENQUEUE(orig, currtpd->parameterArray[i]);
503     }
504
505   }
506
507   /* Update active tasks */
508   {
509     struct genpointerlist * ptr=activetasks->list;
510     while(ptr!=NULL) {
511       struct taskparamdescriptor *tpd=ptr->src;
512       int i;
513       for(i=0; i<tpd->numParameters; i++) {
514         void * orig=tpd->parameterArray[i];
515         ENQUEUE(orig, tpd->parameterArray[i]);
516       }
517       ptr=ptr->inext;
518     }
519     genrehash(activetasks);
520   }
521
522   /* Update failed tasks */
523   {
524     struct genpointerlist * ptr=failedtasks->list;
525     while(ptr!=NULL) {
526       struct taskparamdescriptor *tpd=ptr->src;
527       int i;
528       for(i=0; i<tpd->numParameters; i++) {
529         void * orig=tpd->parameterArray[i];
530         ENQUEUE(orig, tpd->parameterArray[i]);
531       }
532       ptr=ptr->inext;
533     }
534     genrehash(failedtasks);
535   }
536 #endif
537
538 #ifdef MLP
539   {
540     // goes over ready-to-run SESEs
541     struct QI * qitem = headqi;
542     while(qitem!=NULL){
543       SESEcommon* common=(SESEcommon*)qitem->value;
544       if(common==seseCommon){
545         // skip the current running SESE
546         qitem=qitem->next;
547         continue;
548       }
549       SESEcommon* seseRec = (SESEcommon*)(qitem->value);
550       struct garbagelist * gl=(struct garbagelist *)&(seseRec[1]);
551       struct garbagelist * glroot=gl;
552       // update its ascendant SESEs 
553       updateAscendantSESE(seseRec);     
554   
555       while(gl!=NULL) {
556         int i;
557         for(i=0; i<gl->size; i++) {
558           void * orig=gl->array[i];
559           ENQUEUE(orig, gl->array[i]);
560         }
561         gl=gl->next;
562       } 
563       qitem=qitem->next;
564     }
565   }    
566 #endif
567
568
569   while(moreItems()) {
570     void * ptr=dequeue();
571     void *cpy=ptr;
572     int type=((int *)cpy)[0];
573     unsigned INTPTR * pointer;
574 #ifdef TASK
575     if(type==TAGTYPE) {
576       /* Enqueue Tag */
577       /* Nothing is inside */
578       enqueuetag(ptr);
579       continue;
580     }
581 #endif
582     pointer=pointerarray[type];
583     if (pointer==0) {
584       /* Array of primitives */
585       /* Do nothing */
586 #if defined(DSTM)||defined(FASTCHECK)
587       struct ArrayObject *ao=(struct ArrayObject *) ptr;
588       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
589       ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
590       ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
591 #endif
592 #if defined(STM)
593       struct ArrayObject *ao=(struct ArrayObject *) ptr;
594       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
595       SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
596 #endif
597     } else if (((INTPTR)pointer)==1) {
598       /* Array of pointers */
599       struct ArrayObject *ao=(struct ArrayObject *) ptr;
600       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
601 #if (defined(DSTM)||defined(FASTCHECK))
602       ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
603       ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
604 #endif
605 #if defined(STM)
606       SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
607 #endif
608       int length=ao->___length___;
609       int i;
610       for(i=0; i<length; i++) {
611         void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
612         ENQUEUE(objptr, ((void **)(((char *)&ao_cpy->___length___)+sizeof(int)))[i]);
613       }
614     } else {
615       INTPTR size=pointer[0];
616       int i;
617       for(i=1; i<=size; i++) {
618         unsigned int offset=pointer[i];
619         void * objptr=*((void **)(((char *)ptr)+offset));
620         ENQUEUE(objptr, *((void **)(((char *)cpy)+offset)));
621       }
622     }
623   }
624 #ifdef TASK
625   fixtags();
626 #endif
627
628 #ifdef MLP
629   {
630     //rehash memory queues of current running SESEs
631     struct listitem *listptr=list;
632     while(listptr!=NULL){
633       rehashMemoryQueue((SESEcommon*)(listptr->seseCommon));
634       listptr=listptr->next;
635     }
636   }
637 #endif
638
639 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
640   needtocollect=0;
641   pthread_mutex_unlock(&gclistlock);
642 #endif
643 }
644
645 #ifdef TASK
646 /* Fix up the references from tags.  This can't be done earlier,
647    because we don't want tags to keep objects alive */
648 void fixtags() {
649   while(taghead!=NULL) {
650     int i;
651     struct pointerblock *tmp=taghead->next;
652     for(i=0; i<tagindex; i++) {
653       struct ___TagDescriptor___ *tagd=taghead->ptrs[i];
654       struct ___Object___ *obj=tagd->flagptr;
655       struct ___TagDescriptor___ *copy=((struct ___TagDescriptor___**)tagd)[1];
656       if (obj==NULL) {
657         /* Zero object case */
658       } else if (obj->type==-1) {
659         /* Single object case */
660         copy->flagptr=((struct ___Object___**)obj)[1];
661       } else if (obj->type==OBJECTARRAYTYPE) {
662         /* Array case */
663         struct ArrayObject *ao=(struct ArrayObject *) obj;
664         int livecount=0;
665         int j;
666         int k=0;
667         struct ArrayObject *aonew;
668
669         /* Count live objects */
670         for(j=0; j<ao->___cachedCode___; j++) {
671           struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
672           if (tobj->type==-1)
673             livecount++;
674         }
675
676         livecount=((livecount-1)/OBJECTARRAYINTERVAL+1)*OBJECTARRAYINTERVAL;
677         aonew=(struct ArrayObject *) tomalloc(sizeof(struct ArrayObject)+sizeof(struct ___Object___*)*livecount);
678         memcpy(aonew, ao, sizeof(struct ArrayObject));
679         aonew->type=OBJECTARRAYTYPE;
680         aonew->___length___=livecount;
681         copy->flagptr=aonew;
682         for(j=0; j<ao->___cachedCode___; j++) {
683           struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
684           if (tobj->type==-1) {
685             struct ___Object___ * tobjcpy=((struct ___Object___**)tobj)[1];
686             ARRAYSET(aonew, struct ___Object___*, k++,tobjcpy);
687           }
688         }
689         aonew->___cachedCode___=k;
690         for(; k<livecount; k++) {
691           ARRAYSET(aonew, struct ___Object___*, k, NULL);
692         }
693       } else {
694         /* No object live anymore */
695         copy->flagptr=NULL;
696       }
697     }
698     free(taghead);
699     taghead=tmp;
700     tagindex=NUMPTRS;
701   }
702 }
703 #endif
704
705 void * tomalloc(int size) {
706   void * ptr=to_heapptr;
707   if ((size&7)!=0)
708     size+=(8-(size%8));
709   to_heapptr+=size;
710   return ptr;
711 }
712
713 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
714 void checkcollect(void * ptr) {
715   stopforgc((struct garbagelist *)ptr);
716   restartaftergc();
717 }
718
719 #ifdef DSTM
720 void checkcollect2(void * ptr) {
721   int ptrarray[]={1, (int)ptr, (int) revertlist};
722   stopforgc((struct garbagelist *)ptrarray);
723   restartaftergc();
724   revertlist=(struct ___Object___*)ptrarray[2];
725 }
726 #endif
727
728 void stopforgc(struct garbagelist * ptr) {
729 #ifdef DELAYCOMP
730   //just append us to the list
731   ptrstack.prev=ptr;
732   ptr=(struct garbagelist *) &ptrstack;
733 #if defined(STMARRAY)&&!defined(DUALVIEW)
734   arraystack.prev=ptr;
735   ptr=(struct garbagelist *) &arraystack;
736 #endif
737 #endif
738 #ifndef MAC
739   litem.stackptr=ptr;
740 #ifdef THREADS
741   litem.locklist=pthread_getspecific(threadlocks);
742 #endif
743 #if defined(STM)||defined(THREADS)||defined(MLP)
744   litem.base=&memorybase;
745 #endif
746 #ifdef STM
747   litem.tc_size=c_size;
748   litem.tc_table=&c_table;
749   litem.tc_list=&c_list;
750   litem.tc_structs=&c_structs;
751   litem.objlist=newobjs;
752 #ifdef STMSTATS
753   litem.lockedlist=lockedobjs;
754 #endif
755 #endif
756 #else
757   //handle MAC
758   struct listitem *litem=pthread_getspecific(litemkey);
759   litem->stackptr=ptr;
760 #ifdef THREADS
761   litem->locklist=pthread_getspecific(threadlocks);
762 #endif
763 #endif
764   pthread_mutex_lock(&gclistlock);
765   listcount++;
766   if ((listcount+1)==threadcount) {
767     //only do wakeup if we are ready to GC
768     pthread_cond_signal(&gccond);
769   }
770   pthread_mutex_unlock(&gclistlock);
771 }
772
773 void restartaftergc() {
774   if (needtocollect) {
775     pthread_mutex_lock(&gclock); // Wait for GC
776     pthread_mutex_unlock(&gclock);
777   }
778   pthread_mutex_lock(&gclistlock);
779   listcount--;
780   pthread_mutex_unlock(&gclistlock);
781 }
782 #endif
783
784 #if defined(STM)||defined(THREADS)||defined(MLP)
785 #define MEMORYBLOCK 65536
786 void * helper(struct garbagelist *, int);
787 void * mygcmalloc(struct garbagelist * stackptr, int size) {
788   if ((size&7)!=0)
789     size=(size&~7)+8;
790   if (memorybase==NULL||size>(memorytop-memorybase)) {
791     int toallocate=(size>MEMORYBLOCK)?size:MEMORYBLOCK;
792     memorybase=helper(stackptr, toallocate);
793     bzero(memorybase, toallocate);
794     memorytop=memorybase+toallocate;
795   }
796   char *retvalue=memorybase;
797   memorybase+=size;
798   return retvalue;
799 }
800
801 void * helper(struct garbagelist * stackptr, int size) {
802 #else
803 void * mygcmalloc(struct garbagelist * stackptr, int size) {
804 #endif
805   void *ptr;
806 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
807   while (pthread_mutex_trylock(&gclock)!=0) {
808     stopforgc(stackptr);
809     restartaftergc();
810   }
811 #endif
812   ptr=curr_heapptr;
813   if ((size&7)!=0)
814     size=(size&~7)+8;
815   curr_heapptr+=size;
816   if (curr_heapptr>curr_heapgcpoint||curr_heapptr<curr_heapbase) {
817     if (curr_heapbase==0) {
818       /* Need to allocate base heap */
819       curr_heapbase=malloc(INITIALHEAPSIZE);
820       if (curr_heapbase==NULL) {
821         printf("malloc failed.  Garbage colletcor couldn't get enough memory.  Try changing heap size.\n");
822         exit(-1);
823       }
824 #if defined(STM)||defined(THREADS)||defined(MLP)
825 #else
826       bzero(curr_heapbase, INITIALHEAPSIZE);
827 #endif
828       curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
829       curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
830       curr_heapptr=curr_heapbase+size;
831           
832       to_heapbase=malloc(INITIALHEAPSIZE);
833       if (to_heapbase==NULL) {
834         printf("malloc failed.  Garbage collector couldn't get enough memory.  Try changing heap size.\n");
835         exit(-1);
836       }
837       
838       to_heaptop=to_heapbase+INITIALHEAPSIZE;
839       to_heapptr=to_heapbase;
840       ptr=curr_heapbase;
841 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
842       pthread_mutex_unlock(&gclock);
843 #endif
844       return ptr;
845     }
846
847     /* Grow the to heap if necessary */
848     {
849       INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
850       INTPTR to_heapsize=to_heaptop-to_heapbase;
851       INTPTR last_heapsize=0;
852       if (lastgcsize>0) {
853         last_heapsize=HEAPSIZE(lastgcsize, size);
854         if ((last_heapsize&7)!=0)
855           last_heapsize+=(8-(last_heapsize%8));
856       }
857       if (curr_heapsize>last_heapsize)
858         last_heapsize=curr_heapsize;
859       if (last_heapsize>to_heapsize) {
860         free(to_heapbase);
861         to_heapbase=malloc(last_heapsize);
862         if (to_heapbase==NULL) {
863           printf("Error Allocating enough memory\n");
864           exit(-1);
865         }
866         to_heaptop=to_heapbase+last_heapsize;
867         to_heapptr=to_heapbase;
868       }
869     }
870
871     /* Do our collection */
872     collect(stackptr);
873
874     /* Update stat on previous gc size */
875     lastgcsize=(to_heapptr-to_heapbase)+size;
876
877 #ifdef GARBAGESTATS
878     printf("Garbage collected: Old bytes: %u\n", curr_heapptr-curr_heapbase);
879     printf("New space: %u\n", to_heapptr-to_heapbase);
880     printf("Total space: %u\n", to_heaptop-to_heapbase);
881     {
882       int i;
883       for(i=0;i<MAXSTATS;i++) {
884         if (garbagearray[i]!=0)
885           printf("Type=%d Size=%u\n", i, garbagearray[i]);
886       }
887     }
888 #endif
889     /* Flip to/curr heaps */
890     {
891       void * tmp=to_heapbase;
892       to_heapbase=curr_heapbase;
893       curr_heapbase=tmp;
894
895       tmp=to_heaptop;
896       to_heaptop=curr_heaptop;
897       curr_heaptop=tmp;
898
899       tmp=to_heapptr;
900       curr_heapptr=to_heapptr+size;
901       curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
902       to_heapptr=to_heapbase;
903
904       /* Not enough room :(, redo gc */
905       if (curr_heapptr>curr_heapgcpoint) {
906 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
907         pthread_mutex_unlock(&gclock);
908 #endif
909         return mygcmalloc(stackptr, size);
910       }
911
912       bzero(tmp, curr_heaptop-tmp);
913 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
914       pthread_mutex_unlock(&gclock);
915 #endif
916       return tmp;
917     }
918   } else {
919 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
920     pthread_mutex_unlock(&gclock);
921 #endif
922     return ptr;
923   }
924 }
925
926 int gc_createcopy(void * orig, void ** copy_ptr) {
927   if (orig==0) {
928     *copy_ptr=NULL;
929     return 0;
930   } else {
931     int type=((int *)orig)[0];
932     if (type==-1) {
933       *copy_ptr=((void **)orig)[1];
934       return 0;
935     }
936     if (type<NUMCLASSES) {
937       /* We have a normal object */
938 #ifdef STM
939       int size=classsize[type]+sizeof(objheader_t);
940       void *newobj=tomalloc(size);
941       memcpy(newobj,((char *) orig)-sizeof(objheader_t), size);
942       newobj=((char *)newobj)+sizeof(objheader_t);
943 #else
944       int size=classsize[type];
945       void *newobj=tomalloc(size);
946       memcpy(newobj, orig, size);
947 #endif
948 #ifdef GARBAGESTATS
949       garbagearray[type]+=size;
950 #endif
951       ((int *)orig)[0]=-1;
952       ((void **)orig)[1]=newobj;
953       *copy_ptr=newobj;
954       return 1;
955     } else {
956       /* We have an array */
957       struct ArrayObject *ao=(struct ArrayObject *)orig;
958       int elementsize=classsize[type];
959       int length=ao->___length___;
960 #ifdef STM
961 #ifdef STMARRAY
962       int basesize=length*elementsize;
963       basesize=(basesize+LOWMASK)&HIGHMASK;
964       int versionspace=sizeof(int)*2*(basesize>>INDEXSHIFT);
965       int size=sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+versionspace;
966       void *newobj=tomalloc(size);
967       memcpy(newobj, ((char*)orig)-sizeof(objheader_t)-versionspace, size);
968       newobj=((char *)newobj)+sizeof(objheader_t)+versionspace;
969 #else
970       int size=sizeof(struct ArrayObject)+length*elementsize+sizeof(objheader_t);
971       void *newobj=tomalloc(size);
972       memcpy(newobj, ((char*)orig)-sizeof(objheader_t), size);
973       newobj=((char *)newobj)+sizeof(objheader_t);
974 #endif
975 #else
976       int size=sizeof(struct ArrayObject)+length*elementsize;
977       void *newobj=tomalloc(size);
978       memcpy(newobj, orig, size);
979 #endif
980 #ifdef GARBAGESTATS
981       garbagearray[type]+=size;
982 #endif
983       ((int *)orig)[0]=-1;
984       ((void **)orig)[1]=newobj;
985       *copy_ptr=newobj;
986       return 1;
987     }
988   }
989 }
990
991 #ifdef MLP
992 updateForwardList(struct Queue *forwardList, int prevUpdate){
993
994   struct QueueItem * fqItem=getHead(forwardList);
995   while(fqItem!=NULL){
996     SESEcommon* seseRec = (SESEcommon*)(fqItem->objectptr);
997     struct garbagelist * gl=(struct garbagelist *)&(seseRec[1]);
998     if(prevUpdate==TRUE){
999       updateAscendantSESE(seseRec);     
1000     }
1001     // do something here
1002     while(gl!=NULL) {
1003       int i;
1004       for(i=0; i<gl->size; i++) {
1005         void * orig=gl->array[i];
1006         ENQUEUE(orig, gl->array[i]);
1007       }
1008       gl=gl->next;
1009     }    
1010     // iterate forwarding list of seseRec
1011     struct Queue* fList=seseRec->forwardList;
1012     updateForwardList(fList,prevUpdate);   
1013     fqItem=getNextQueueItem(fqItem);
1014   }   
1015
1016 }
1017
1018 updateMemoryQueue(SESEcommon_p seseParent){
1019   // update memory queue
1020   int i,binidx;
1021   for(i=0; i<seseParent->numMemoryQueue; i++){
1022     MemoryQueue *memoryQueue=seseParent->memoryQueueArray[i];
1023     MemoryQueueItem *memoryItem=memoryQueue->head;
1024     while(memoryItem!=NULL){
1025       if(memoryItem->type==HASHTABLE){
1026         Hashtable *ht=(Hashtable*)memoryItem;
1027         for(binidx=0; binidx<NUMBINS; binidx++){
1028           BinElement *bin=ht->array[binidx];
1029           BinItem *binItem=bin->head;
1030           while(binItem!=NULL){
1031             if(binItem->type==READBIN){
1032               ReadBinItem* readBinItem=(ReadBinItem*)binItem;
1033               int ridx;
1034               for(ridx=0; ridx<readBinItem->index; ridx++){
1035                 REntry *rentry=readBinItem->array[ridx];
1036                 SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1037                 struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1038                 updateAscendantSESE(seseRec);
1039                 while(gl!=NULL) {
1040                   int i;
1041                   for(i=0; i<gl->size; i++) {
1042                     void * orig=gl->array[i];
1043                     ENQUEUE(orig, gl->array[i]);
1044                   }
1045                   gl=gl->next;
1046                 } 
1047               } 
1048             }else{ //writebin
1049               REntry *rentry=((WriteBinItem*)binItem)->val;
1050               SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1051               struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1052               updateAscendantSESE(seseRec);
1053               while(gl!=NULL) {
1054                 int i;
1055                 for(i=0; i<gl->size; i++) {
1056                   void * orig=gl->array[i];
1057                   ENQUEUE(orig, gl->array[i]);
1058                 }
1059                 gl=gl->next;
1060               } 
1061             }
1062             binItem=binItem->next;
1063           }
1064         }
1065       }else if(memoryItem->type==VECTOR){
1066         Vector *vt=(Vector*)memoryItem;
1067         int idx;
1068         for(idx=0; idx<vt->index; idx++){
1069           REntry *rentry=vt->array[idx];
1070           if(rentry!=NULL){
1071             SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1072             struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1073             updateAscendantSESE(seseRec);
1074             while(gl!=NULL) {
1075               int i;
1076               for(i=0; i<gl->size; i++) {
1077                 void * orig=gl->array[i];
1078                 ENQUEUE(orig, gl->array[i]);
1079               }
1080               gl=gl->next;
1081             } 
1082           }
1083         }
1084       }else if(memoryItem->type==SINGLEITEM){
1085         SCC *scc=(SCC*)memoryItem;
1086         REntry *rentry=scc->val;
1087         if(rentry!=NULL){
1088           SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1089           struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1090           updateAscendantSESE(seseRec);
1091           while(gl!=NULL) {
1092             int i;
1093             for(i=0; i<gl->size; i++) {
1094               void * orig=gl->array[i];
1095               ENQUEUE(orig, gl->array[i]);
1096             }
1097             gl=gl->next;
1098           } 
1099         }
1100       }
1101       memoryItem=memoryItem->next;
1102     }
1103   }     
1104  }
1105  
1106  updateAscendantSESE(SESEcommon* seseRec){   
1107   int prevIdx;
1108   for(prevIdx=0; prevIdx<(seseRec->numDependentSESErecords); prevIdx++){
1109     SESEcommon* prevSESE = (SESEcommon*) 
1110       (
1111        ((INTPTR)seseRec) + 
1112        seseRec->offsetToDepSESErecords +
1113        (sizeof(INTPTR)*prevIdx)
1114       );
1115        
1116     if(prevSESE!=NULL){
1117       struct garbagelist * prevgl=(struct garbagelist *)&(((SESEcommon*)(prevSESE))[1]);
1118       while(prevgl!=NULL) {
1119         int i;
1120         for(i=0; i<prevgl->size; i++) {
1121           void * orig=prevgl->array[i];
1122           ENQUEUE(orig, prevgl->array[i]);
1123         }
1124         prevgl=prevgl->next;
1125       } 
1126     }
1127   }
1128   
1129  }
1130 #endif
1131
1132 int within(void *ptr){ //debug function
1133   if(ptr>curr_heapptr || ptr<curr_heapbase){
1134     __asm__ __volatile__ ("int $3");  // breakpoint
1135   }
1136 }