accidental update
[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       struct garbagelist * gl=(struct garbagelist *)&(((SESEcommon*)(qitem->value))[1]);
550       struct garbagelist * glroot=gl;
551       // update its ascendant SESEs 
552       updateAscendantSESE(gl);  
553   
554       while(gl!=NULL) {
555         int i;
556         for(i=0; i<gl->size; i++) {
557           void * orig=gl->array[i];
558           ENQUEUE(orig, gl->array[i]);
559         }
560         gl=gl->next;
561       } 
562       qitem=qitem->next;
563     }
564   }    
565 #endif
566
567
568   while(moreItems()) {
569     void * ptr=dequeue();
570     void *cpy=ptr;
571     int type=((int *)cpy)[0];
572     unsigned INTPTR * pointer;
573 #ifdef TASK
574     if(type==TAGTYPE) {
575       /* Enqueue Tag */
576       /* Nothing is inside */
577       enqueuetag(ptr);
578       continue;
579     }
580 #endif
581     pointer=pointerarray[type];
582     if (pointer==0) {
583       /* Array of primitives */
584       /* Do nothing */
585 #if defined(DSTM)||defined(FASTCHECK)
586       struct ArrayObject *ao=(struct ArrayObject *) ptr;
587       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
588       ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
589       ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
590 #endif
591 #if defined(STM)
592       struct ArrayObject *ao=(struct ArrayObject *) ptr;
593       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
594       SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
595 #endif
596     } else if (((INTPTR)pointer)==1) {
597       /* Array of pointers */
598       struct ArrayObject *ao=(struct ArrayObject *) ptr;
599       struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
600 #if (defined(DSTM)||defined(FASTCHECK))
601       ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
602       ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
603 #endif
604 #if defined(STM)
605       SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
606 #endif
607       int length=ao->___length___;
608       int i;
609       for(i=0; i<length; i++) {
610         void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
611         ENQUEUE(objptr, ((void **)(((char *)&ao_cpy->___length___)+sizeof(int)))[i]);
612       }
613     } else {
614       INTPTR size=pointer[0];
615       int i;
616       for(i=1; i<=size; i++) {
617         unsigned int offset=pointer[i];
618         void * objptr=*((void **)(((char *)ptr)+offset));
619         ENQUEUE(objptr, *((void **)(((char *)cpy)+offset)));
620       }
621     }
622   }
623 #ifdef TASK
624   fixtags();
625 #endif
626
627 #ifdef MLP
628   {
629     //rehash memory queues of current running SESEs
630     struct listitem *listptr=list;
631     while(listptr!=NULL){
632       rehashMemoryQueue((SESEcommon*)(listptr->seseCommon));
633       listptr=listptr->next;
634     }
635   }
636 #endif
637
638 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
639   needtocollect=0;
640   pthread_mutex_unlock(&gclistlock);
641 #endif
642 }
643
644 #ifdef TASK
645 /* Fix up the references from tags.  This can't be done earlier,
646    because we don't want tags to keep objects alive */
647 void fixtags() {
648   while(taghead!=NULL) {
649     int i;
650     struct pointerblock *tmp=taghead->next;
651     for(i=0; i<tagindex; i++) {
652       struct ___TagDescriptor___ *tagd=taghead->ptrs[i];
653       struct ___Object___ *obj=tagd->flagptr;
654       struct ___TagDescriptor___ *copy=((struct ___TagDescriptor___**)tagd)[1];
655       if (obj==NULL) {
656         /* Zero object case */
657       } else if (obj->type==-1) {
658         /* Single object case */
659         copy->flagptr=((struct ___Object___**)obj)[1];
660       } else if (obj->type==OBJECTARRAYTYPE) {
661         /* Array case */
662         struct ArrayObject *ao=(struct ArrayObject *) obj;
663         int livecount=0;
664         int j;
665         int k=0;
666         struct ArrayObject *aonew;
667
668         /* Count live objects */
669         for(j=0; j<ao->___cachedCode___; j++) {
670           struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
671           if (tobj->type==-1)
672             livecount++;
673         }
674
675         livecount=((livecount-1)/OBJECTARRAYINTERVAL+1)*OBJECTARRAYINTERVAL;
676         aonew=(struct ArrayObject *) tomalloc(sizeof(struct ArrayObject)+sizeof(struct ___Object___*)*livecount);
677         memcpy(aonew, ao, sizeof(struct ArrayObject));
678         aonew->type=OBJECTARRAYTYPE;
679         aonew->___length___=livecount;
680         copy->flagptr=aonew;
681         for(j=0; j<ao->___cachedCode___; j++) {
682           struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
683           if (tobj->type==-1) {
684             struct ___Object___ * tobjcpy=((struct ___Object___**)tobj)[1];
685             ARRAYSET(aonew, struct ___Object___*, k++,tobjcpy);
686           }
687         }
688         aonew->___cachedCode___=k;
689         for(; k<livecount; k++) {
690           ARRAYSET(aonew, struct ___Object___*, k, NULL);
691         }
692       } else {
693         /* No object live anymore */
694         copy->flagptr=NULL;
695       }
696     }
697     free(taghead);
698     taghead=tmp;
699     tagindex=NUMPTRS;
700   }
701 }
702 #endif
703
704 void * tomalloc(int size) {
705   void * ptr=to_heapptr;
706   if ((size&7)!=0)
707     size+=(8-(size%8));
708   to_heapptr+=size;
709   return ptr;
710 }
711
712 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
713 void checkcollect(void * ptr) {
714   stopforgc((struct garbagelist *)ptr);
715   restartaftergc();
716 }
717
718 #ifdef DSTM
719 void checkcollect2(void * ptr) {
720   int ptrarray[]={1, (int)ptr, (int) revertlist};
721   stopforgc((struct garbagelist *)ptrarray);
722   restartaftergc();
723   revertlist=(struct ___Object___*)ptrarray[2];
724 }
725 #endif
726
727 void stopforgc(struct garbagelist * ptr) {
728 #ifdef DELAYCOMP
729   //just append us to the list
730   ptrstack.prev=ptr;
731   ptr=(struct garbagelist *) &ptrstack;
732 #if defined(STMARRAY)&&!defined(DUALVIEW)
733   arraystack.prev=ptr;
734   ptr=(struct garbagelist *) &arraystack;
735 #endif
736 #endif
737 #ifndef MAC
738   litem.stackptr=ptr;
739 #ifdef THREADS
740   litem.locklist=pthread_getspecific(threadlocks);
741 #endif
742 #if defined(STM)||defined(THREADS)||defined(MLP)
743   litem.base=&memorybase;
744 #endif
745 #ifdef STM
746   litem.tc_size=c_size;
747   litem.tc_table=&c_table;
748   litem.tc_list=&c_list;
749   litem.tc_structs=&c_structs;
750   litem.objlist=newobjs;
751 #ifdef STMSTATS
752   litem.lockedlist=lockedobjs;
753 #endif
754 #endif
755 #else
756   //handle MAC
757   struct listitem *litem=pthread_getspecific(litemkey);
758   litem->stackptr=ptr;
759 #ifdef THREADS
760   litem->locklist=pthread_getspecific(threadlocks);
761 #endif
762 #endif
763   pthread_mutex_lock(&gclistlock);
764   listcount++;
765   if ((listcount+1)==threadcount) {
766     //only do wakeup if we are ready to GC
767     pthread_cond_signal(&gccond);
768   }
769   pthread_mutex_unlock(&gclistlock);
770 }
771
772 void restartaftergc() {
773   if (needtocollect) {
774     pthread_mutex_lock(&gclock); // Wait for GC
775     pthread_mutex_unlock(&gclock);
776   }
777   pthread_mutex_lock(&gclistlock);
778   listcount--;
779   pthread_mutex_unlock(&gclistlock);
780 }
781 #endif
782
783 #if defined(STM)||defined(THREADS)||defined(MLP)
784 #define MEMORYBLOCK 65536
785 void * helper(struct garbagelist *, int);
786 void * mygcmalloc(struct garbagelist * stackptr, int size) {
787   if ((size&7)!=0)
788     size=(size&~7)+8;
789   if (memorybase==NULL||size>(memorytop-memorybase)) {
790     int toallocate=(size>MEMORYBLOCK)?size:MEMORYBLOCK;
791     memorybase=helper(stackptr, toallocate);
792     bzero(memorybase, toallocate);
793     memorytop=memorybase+toallocate;
794   }
795   char *retvalue=memorybase;
796   memorybase+=size;
797   return retvalue;
798 }
799
800 void * helper(struct garbagelist * stackptr, int size) {
801 #else
802 void * mygcmalloc(struct garbagelist * stackptr, int size) {
803 #endif
804   void *ptr;
805 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
806   while (pthread_mutex_trylock(&gclock)!=0) {
807     stopforgc(stackptr);
808     restartaftergc();
809   }
810 #endif
811   ptr=curr_heapptr;
812   if ((size&7)!=0)
813     size=(size&~7)+8;
814   curr_heapptr+=size;
815   if (curr_heapptr>curr_heapgcpoint||curr_heapptr<curr_heapbase) {
816     if (curr_heapbase==0) {
817       /* Need to allocate base heap */
818       curr_heapbase=malloc(INITIALHEAPSIZE);
819       if (curr_heapbase==NULL) {
820         printf("malloc failed.  Garbage colletcor couldn't get enough memory.  Try changing heap size.\n");
821         exit(-1);
822       }
823 #if defined(STM)||defined(THREADS)||defined(MLP)
824 #else
825       bzero(curr_heapbase, INITIALHEAPSIZE);
826 #endif
827       curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
828       curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
829       curr_heapptr=curr_heapbase+size;
830           
831       to_heapbase=malloc(INITIALHEAPSIZE);
832       if (to_heapbase==NULL) {
833         printf("malloc failed.  Garbage collector couldn't get enough memory.  Try changing heap size.\n");
834         exit(-1);
835       }
836       
837       to_heaptop=to_heapbase+INITIALHEAPSIZE;
838       to_heapptr=to_heapbase;
839       ptr=curr_heapbase;
840 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
841       pthread_mutex_unlock(&gclock);
842 #endif
843       return ptr;
844     }
845
846     /* Grow the to heap if necessary */
847     {
848       INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
849       INTPTR to_heapsize=to_heaptop-to_heapbase;
850       INTPTR last_heapsize=0;
851       if (lastgcsize>0) {
852         last_heapsize=HEAPSIZE(lastgcsize, size);
853         if ((last_heapsize&7)!=0)
854           last_heapsize+=(8-(last_heapsize%8));
855       }
856       if (curr_heapsize>last_heapsize)
857         last_heapsize=curr_heapsize;
858       if (last_heapsize>to_heapsize) {
859         free(to_heapbase);
860         to_heapbase=malloc(last_heapsize);
861         if (to_heapbase==NULL) {
862           printf("Error Allocating enough memory\n");
863           exit(-1);
864         }
865         to_heaptop=to_heapbase+last_heapsize;
866         to_heapptr=to_heapbase;
867       }
868     }
869
870     /* Do our collection */
871     collect(stackptr);
872
873     /* Update stat on previous gc size */
874     lastgcsize=(to_heapptr-to_heapbase)+size;
875
876 #ifdef GARBAGESTATS
877     printf("Garbage collected: Old bytes: %u\n", curr_heapptr-curr_heapbase);
878     printf("New space: %u\n", to_heapptr-to_heapbase);
879     printf("Total space: %u\n", to_heaptop-to_heapbase);
880     {
881       int i;
882       for(i=0;i<MAXSTATS;i++) {
883         if (garbagearray[i]!=0)
884           printf("Type=%d Size=%u\n", i, garbagearray[i]);
885       }
886     }
887 #endif
888     /* Flip to/curr heaps */
889     {
890       void * tmp=to_heapbase;
891       to_heapbase=curr_heapbase;
892       curr_heapbase=tmp;
893
894       tmp=to_heaptop;
895       to_heaptop=curr_heaptop;
896       curr_heaptop=tmp;
897
898       tmp=to_heapptr;
899       curr_heapptr=to_heapptr+size;
900       curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
901       to_heapptr=to_heapbase;
902
903       /* Not enough room :(, redo gc */
904       if (curr_heapptr>curr_heapgcpoint) {
905 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
906         pthread_mutex_unlock(&gclock);
907 #endif
908         return mygcmalloc(stackptr, size);
909       }
910
911       bzero(tmp, curr_heaptop-tmp);
912 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
913       pthread_mutex_unlock(&gclock);
914 #endif
915       return tmp;
916     }
917   } else {
918 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
919     pthread_mutex_unlock(&gclock);
920 #endif
921     return ptr;
922   }
923 }
924
925 int gc_createcopy(void * orig, void ** copy_ptr) {
926   if (orig==0) {
927     *copy_ptr=NULL;
928     return 0;
929   } else {
930     int type=((int *)orig)[0];
931     if (type==-1) {
932       *copy_ptr=((void **)orig)[1];
933       return 0;
934     }
935     if (type<NUMCLASSES) {
936       /* We have a normal object */
937 #ifdef STM
938       int size=classsize[type]+sizeof(objheader_t);
939       void *newobj=tomalloc(size);
940       memcpy(newobj,((char *) orig)-sizeof(objheader_t), size);
941       newobj=((char *)newobj)+sizeof(objheader_t);
942 #else
943       int size=classsize[type];
944       void *newobj=tomalloc(size);
945       memcpy(newobj, orig, size);
946 #endif
947 #ifdef GARBAGESTATS
948       garbagearray[type]+=size;
949 #endif
950       ((int *)orig)[0]=-1;
951       ((void **)orig)[1]=newobj;
952       *copy_ptr=newobj;
953       return 1;
954     } else {
955       /* We have an array */
956       struct ArrayObject *ao=(struct ArrayObject *)orig;
957       int elementsize=classsize[type];
958       int length=ao->___length___;
959 #ifdef STM
960 #ifdef STMARRAY
961       int basesize=length*elementsize;
962       basesize=(basesize+LOWMASK)&HIGHMASK;
963       int versionspace=sizeof(int)*2*(basesize>>INDEXSHIFT);
964       int size=sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+versionspace;
965       void *newobj=tomalloc(size);
966       memcpy(newobj, ((char*)orig)-sizeof(objheader_t)-versionspace, size);
967       newobj=((char *)newobj)+sizeof(objheader_t)+versionspace;
968 #else
969       int size=sizeof(struct ArrayObject)+length*elementsize+sizeof(objheader_t);
970       void *newobj=tomalloc(size);
971       memcpy(newobj, ((char*)orig)-sizeof(objheader_t), size);
972       newobj=((char *)newobj)+sizeof(objheader_t);
973 #endif
974 #else
975       int size=sizeof(struct ArrayObject)+length*elementsize;
976       void *newobj=tomalloc(size);
977       memcpy(newobj, orig, size);
978 #endif
979 #ifdef GARBAGESTATS
980       garbagearray[type]+=size;
981 #endif
982       ((int *)orig)[0]=-1;
983       ((void **)orig)[1]=newobj;
984       *copy_ptr=newobj;
985       return 1;
986     }
987   }
988 }
989
990 #ifdef MLP
991 updateForwardList(struct Queue *forwardList, int prevUpdate){
992
993   struct QueueItem * fqItem=getHead(forwardList);
994   while(fqItem!=NULL){
995     struct garbagelist * gl=(struct garbagelist *)&(((SESEcommon*)(fqItem->objectptr))[1]);
996     if(prevUpdate==TRUE){
997       updateAscendantSESE(gl);  
998     }
999     // do something here
1000     while(gl!=NULL) {
1001       int i;
1002          for(i=0; i<gl->size; i++) {
1003            void * orig=gl->array[i];
1004            ENQUEUE(orig, gl->array[i]);
1005          }
1006          gl=gl->next;
1007     }    
1008     // iterate forwarding list of seseRec      
1009     SESEcommon *common=(SESEcommon*)fqItem->objectptr;
1010     struct Queue* fList=common->forwardList;
1011     updateForwardList(fList,prevUpdate);   
1012     fqItem=getNextQueueItem(fqItem);
1013   }   
1014
1015 }
1016
1017 updateMemoryQueue(SESEcommon_p seseParent){
1018   // update memory queue
1019   int i,binidx;
1020   for(i=0; i<seseParent->numMemoryQueue; i++){
1021     MemoryQueue *memoryQueue=seseParent->memoryQueueArray[i];
1022     MemoryQueueItem *memoryItem=memoryQueue->head;
1023     while(memoryItem!=NULL){
1024       if(memoryItem->type==HASHTABLE){
1025         Hashtable *ht=(Hashtable*)memoryItem;
1026         for(binidx=0; binidx<NUMBINS; binidx++){
1027           BinElement *bin=ht->array[binidx];
1028           BinItem *binItem=bin->head;
1029           while(binItem!=NULL){
1030             if(binItem->type==READBIN){
1031               ReadBinItem* readBinItem=(ReadBinItem*)binItem;
1032               int ridx;
1033               for(ridx=0; ridx<readBinItem->index; ridx++){
1034                 REntry *rentry=readBinItem->array[ridx];                  
1035                 struct garbagelist * gl= (struct garbagelist *)&(((SESEcommon*)(rentry->seseRec))[1]);
1036                 updateAscendantSESE(gl);
1037                 while(gl!=NULL) {
1038                   int i;
1039                   for(i=0; i<gl->size; i++) {
1040                     void * orig=gl->array[i];
1041                     ENQUEUE(orig, gl->array[i]);
1042                   }
1043                   gl=gl->next;
1044                 } 
1045               } 
1046             }else{ //writebin
1047               REntry *rentry=((WriteBinItem*)binItem)->val;
1048               struct garbagelist * gl= (struct garbagelist *)&(((SESEcommon*)(rentry->seseRec))[1]);
1049               updateAscendantSESE(gl);
1050               while(gl!=NULL) {
1051                 int i;
1052                 for(i=0; i<gl->size; i++) {
1053                   void * orig=gl->array[i];
1054                   ENQUEUE(orig, gl->array[i]);
1055                 }
1056                 gl=gl->next;
1057               } 
1058             }
1059             binItem=binItem->next;
1060           }
1061         }
1062       }else if(memoryItem->type==VECTOR){
1063         Vector *vt=(Vector*)memoryItem;
1064         int idx;
1065         for(idx=0; idx<vt->index; idx++){
1066           REntry *rentry=vt->array[idx];
1067           if(rentry!=NULL){
1068             struct garbagelist * gl= (struct garbagelist *)&(((SESEcommon*)(rentry->seseRec))[1]);
1069             updateAscendantSESE(gl);
1070             while(gl!=NULL) {
1071               int i;
1072               for(i=0; i<gl->size; i++) {
1073                 void * orig=gl->array[i];
1074                 ENQUEUE(orig, gl->array[i]);
1075               }
1076               gl=gl->next;
1077             } 
1078           }
1079         }
1080       }else if(memoryItem->type==SINGLEITEM){
1081         SCC *scc=(SCC*)memoryItem;
1082         REntry *rentry=scc->val;
1083         if(rentry!=NULL){
1084           struct garbagelist * gl= (struct garbagelist *)&(((SESEcommon*)(rentry->seseRec))[1]);
1085           updateAscendantSESE(gl);
1086           while(gl!=NULL) {
1087             int i;
1088             for(i=0; i<gl->size; i++) {
1089               void * orig=gl->array[i];
1090               ENQUEUE(orig, gl->array[i]);
1091             }
1092             gl=gl->next;
1093           } 
1094         }
1095       }
1096       memoryItem=memoryItem->next;
1097     }
1098   }     
1099  }
1100  
1101 updateAscendantSESE(struct garbagelist *gl){ 
1102   int offsetsize=*((int*)((void*)gl-sizeof(int)));
1103   int prevSESECount=*((int*)((void*)gl+offsetsize));
1104   INTPTR tailaddr=(INTPTR)((void*)gl+offsetsize+sizeof(int));
1105   int prevIdx;
1106   for(prevIdx=0; prevIdx<prevSESECount; prevIdx++){
1107     SESEcommon* prevSESE=(SESEcommon*)*((INTPTR*)(tailaddr+sizeof(void*)*prevIdx));
1108     if(prevSESE!=NULL){
1109       struct garbagelist * prevgl=(struct garbagelist *)&(((SESEcommon*)(prevSESE))[1]);
1110       while(prevgl!=NULL) {
1111         int i;
1112         for(i=0; i<prevgl->size; i++) {
1113           void * orig=prevgl->array[i];
1114           ENQUEUE(orig, prevgl->array[i]);
1115         }
1116         prevgl=prevgl->next;
1117       } 
1118     }
1119   }
1120 }
1121 #endif
1122
1123 int within(void *ptr){ //debug function
1124   if(ptr>curr_heapptr || ptr<curr_heapbase){
1125     __asm__ __volatile__ ("int $3");  // breakpoint
1126   }
1127 }