3 #include "structdefs.h"
5 #include "SimpleHash.h"
7 #include "GenericHashtable.h"
9 #if defined(THREADS) || defined(DSTM) || defined(STM)
14 #include "workschedule.h"
15 extern int numWorkSchedWorkers;
24 #include <DSTM/interface_recovery/dstm.h>
26 #include <DSTM/interface/dstm.h>
33 #include "delaycomp.h"
39 #ifndef INITIALHEAPSIZE_MB
40 #define INITIALHEAPSIZE_MB (256)
43 #define INITIALHEAPSIZE INITIALHEAPSIZE_MB*1024*1024L
44 #define GCPOINT(x) ((INTPTR)((x)*0.99))
45 /* This define takes in how full the heap is initially and returns a new heap size to use */
46 #define HEAPSIZE(x,y) ((INTPTR)(x+y))*2
49 extern struct genhashtable * activetasks;
51 extern struct parameterwrapper * objectqueues[NUMCLASSES];
53 extern struct genhashtable * failedtasks;
54 extern struct taskparamdescriptor *currtpd;
55 extern struct ctable *forward;
56 extern struct ctable *reverse;
57 extern struct RuntimeHash *fdtoobject;
62 long garbagearray[MAXSTATS];
65 #if defined(THREADS) || defined(DSTM) || defined(STM)||defined(MLP)
67 struct listitem * list=NULL;
70 __thread struct listitem litem;
75 __thread SESEcommon* seseCommon;
78 //Need to check if pointers are transaction pointers
79 //this also catches the special flag value of 1 for local copies
81 #define ENQUEUE(orig, dst) \
82 if ((!(((unsigned int)orig)&0x1))) { \
83 if (orig>=curr_heapbase&&orig<curr_heaptop) { \
85 if (gc_createcopy(orig,©)) \
91 #define ENQUEUE(orig, dst) \
92 if (orig>=curr_heapbase&&orig<curr_heaptop) { \
94 if (gc_createcopy(orig,©)) \
98 #define SENQUEUE(orig, dst) \
101 if (gc_createcopy(orig,©)) \
105 #elif defined(FASTCHECK)
106 #define ENQUEUE(orig, dst) \
107 if (((unsigned int)orig)!=1) { \
109 if (gc_createcopy(orig,©)) \
113 #define ENQUEUE(orig, dst) \
114 if (orig>=curr_heapbase&&orig<curr_heaptop) { \
116 if (gc_createcopy(orig,©)) \
123 struct pointerblock {
124 void * ptrs[NUMPTRS];
125 struct pointerblock *next;
128 void * curr_heapbase=0;
129 void * curr_heapptr=0;
130 void * curr_heapgcpoint=0;
131 void * curr_heaptop=0;
133 void * to_heapbase=0;
139 struct pointerblock *head=NULL;
141 struct pointerblock *tail=NULL;
143 struct pointerblock *spare=NULL;
145 void enqueue(void *ptr) {
146 if (headindex==NUMPTRS) {
147 struct pointerblock * tmp;
151 } else tmp=malloc(sizeof(struct pointerblock));
156 head->ptrs[headindex++]=ptr;
160 if (tailindex==NUMPTRS) {
161 struct pointerblock *tmp=tail;
169 return tail->ptrs[tailindex++];
173 void fixobjlist(struct objlist * ptr) {
176 for(i=0;i<ptr->offset;i++) {
177 SENQUEUE(ptr->objs[i], ptr->objs[i]);
183 void fixtable(chashlistnode_t ** tc_table, chashlistnode_t **tc_list, cliststruct_t **cstr, unsigned int tc_size) {
184 unsigned int mask=(tc_size<<4)-1;
185 chashlistnode_t *node=calloc(tc_size, sizeof(chashlistnode_t));
186 chashlistnode_t *ptr=*tc_table;
187 chashlistnode_t *curr;
191 chashlistnode_t *newlist=NULL;
192 for(i=0;i<tc_size;i++) {
195 do { //Inner loop to go through linked lists
197 chashlistnode_t *tmp,*next;
199 if ((key=(void *)curr->key) == 0) { //Exit inner loop if there the first element is 0
200 break; //key = val =0 for element if not present within the hash table
203 if (curr->val>=curr_heapbase&&curr->val<curr_heaptop) {
204 SENQUEUE(curr->val, curr->val);
206 //rewrite transaction cache entry
207 void *vptr=curr->val;
208 int type=((int *)vptr)[0];
209 unsigned INTPTR *pointer=pointerarray[type];
211 //array of primitives - do nothing
212 struct ArrayObject *ao=(struct ArrayObject *) vptr;
213 SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___));
214 } else if (((INTPTR)pointer)==1) {
216 struct ArrayObject *ao=(struct ArrayObject *) vptr;
217 int length=ao->___length___;
219 SENQUEUE((void *)ao->___objlocation___, *((void **)&ao->___objlocation___));
221 int lowindex=ao->lowindex;
222 int highindex=ao->highindex;
224 for(j=lowindex; j<=highindex; j++) {
225 unsigned int lockval;
226 GETLOCKVAL(lockval, ao, j);
227 if (lockval!=STMNONE) {
228 int lowi=(j<<INDEXSHIFT)/sizeof(void *);
229 int highi=lowi+(INDEXLENGTH/sizeof(void *));
230 for(i=lowi; i<highi;i++) {
232 for(i=0; i<length; i++) {
234 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
235 SENQUEUE(objptr, ((void **)(((char *)&ao->___length___)+sizeof(int)))[i]);
242 INTPTR size=pointer[0];
244 for(i=1; i<=size; i++) {
245 unsigned int offset=pointer[i];
246 void * objptr=*((void **)(((char *)vptr)+offset));
247 SENQUEUE(objptr, *((void **)(((char *)vptr)+offset)));
253 index = (((unsigned INTPTR)key) & mask) >>4;
257 // Insert into the new table
259 tmp->key = curr->key;
260 tmp->val = curr->val;
263 } else if (isfirst) {
264 chashlistnode_t *newnode;
265 if ((*cstr)->num<NUMCLIST) {
266 newnode=&(*cstr)->array[(*cstr)->num];
270 cliststruct_t *tcl=calloc(1,sizeof(cliststruct_t));
273 newnode=&tcl->array[0];
276 newnode->key = curr->key;
277 newnode->val = curr->val;
278 newnode->next = tmp->next;
279 newnode->lnext=newlist;
285 curr->next=tmp->next;
299 if ((head==tail)&&(tailindex==headindex))
305 struct pointerblock *taghead=NULL;
308 void enqueuetag(struct ___TagDescriptor___ *ptr) {
309 if (tagindex==NUMPTRS) {
310 struct pointerblock * tmp=malloc(sizeof(struct pointerblock));
315 taghead->ptrs[tagindex++]=ptr;
319 #if defined(STM)||defined(THREADS)||defined(MLP)
320 __thread char * memorybase=NULL;
321 __thread char * memorytop=NULL;
325 void collect(struct garbagelist * stackptr) {
326 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
328 pthread_mutex_lock(&gclistlock);
330 if ((listcount+1)==threadcount) {
331 break; /* Have all other threads stopped */
333 pthread_cond_wait(&gccond, &gclistlock);
337 ptrstack.prev=stackptr;
338 stackptr=(struct garbagelist *) &ptrstack;
339 #if defined(STMARRAY)&&!defined(DUALVIEW)
340 arraystack.prev=stackptr;
341 stackptr=(struct garbagelist *) &arraystack;
348 for(i=0;i<MAXSTATS;i++)
356 head=tail=malloc(sizeof(struct pointerblock));
362 taghead=malloc(sizeof(struct pointerblock));
369 fixtable(&c_table, &c_list, &c_structs, c_size);
372 fixobjlist(lockedobjs);
376 #if defined(STM)||defined(THREADS)||defined(MLP)
380 /* Check current stack */
381 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
383 struct listitem *listptr=list;
387 while(stackptr!=NULL) {
389 for(i=0; i<stackptr->size; i++) {
390 void * orig=stackptr->array[i];
391 ENQUEUE(orig, stackptr->array[i]);
393 stackptr=stackptr->next;
395 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
396 /* Go to next thread */
399 if (listptr==&litem) {
401 // update forward list & memory queue for the current SESE
402 updateForwardList(((SESEcommon*)listptr->seseCommon)->forwardList,FALSE);
403 updateMemoryQueue((SESEcommon*)(listptr->seseCommon));
405 listptr=listptr->next;
409 struct listitem *litem=pthread_getspecific(litemkey);
410 if (listptr==litem) {
411 listptr=listptr->next;
418 void * orig=listptr->locklist;
419 ENQUEUE(orig, listptr->locklist);
422 if ((*listptr->tc_table)!=NULL) {
423 fixtable(listptr->tc_table, listptr->tc_list, listptr->tc_structs, listptr->tc_size);
424 fixobjlist(listptr->objlist);
426 fixobjlist(listptr->lockedlist);
430 #if defined(STM)||defined(THREADS)||defined(MLP)
431 *(listptr->base)=NULL;
434 // update forward list & memory queue for all running SESEs.
435 updateForwardList(((SESEcommon*)listptr->seseCommon)->forwardList,FALSE);
436 updateMemoryQueue((SESEcommon*)(listptr->seseCommon));
438 stackptr=listptr->stackptr;
439 listptr=listptr->next;
447 ENQUEUE(___fcrevert___, ___fcrevert___);
452 /* Update objectsets */
454 for(i=0; i<NUMCLASSES; i++) {
455 #if !defined(MULTICORE)
456 struct parameterwrapper * p=objectqueues[i];
458 struct ObjectHash * set=p->objectset;
459 struct ObjectNode * ptr=set->listhead;
461 void *orig=(void *)ptr->key;
462 ENQUEUE(orig, *((void **)(&ptr->key)));
465 ObjectHashrehash(set); /* Rehash the table */
474 struct cnode * ptr=forward->listhead;
476 void * orig=(void *)ptr->key;
477 ENQUEUE(orig, *((void **)(&ptr->key)));
480 crehash(forward); /* Rehash the table */
484 struct cnode * ptr=reverse->listhead;
486 void *orig=(void *)ptr->val;
487 ENQUEUE(orig, *((void**)(&ptr->val)));
494 struct RuntimeNode * ptr=fdtoobject->listhead;
496 void *orig=(void *)ptr->data;
497 ENQUEUE(orig, *((void**)(&ptr->data)));
503 /* Update current task descriptor */
505 for(i=0; i<currtpd->numParameters; i++) {
506 void *orig=currtpd->parameterArray[i];
507 ENQUEUE(orig, currtpd->parameterArray[i]);
512 /* Update active tasks */
514 struct genpointerlist * ptr=activetasks->list;
516 struct taskparamdescriptor *tpd=ptr->src;
518 for(i=0; i<tpd->numParameters; i++) {
519 void * orig=tpd->parameterArray[i];
520 ENQUEUE(orig, tpd->parameterArray[i]);
524 genrehash(activetasks);
527 /* Update failed tasks */
529 struct genpointerlist * ptr=failedtasks->list;
531 struct taskparamdescriptor *tpd=ptr->src;
533 for(i=0; i<tpd->numParameters; i++) {
534 void * orig=tpd->parameterArray[i];
535 ENQUEUE(orig, tpd->parameterArray[i]);
539 genrehash(failedtasks);
556 // goes over ready-to-run SESEs
557 for( i = 0; i < numWorkSchedWorkers; ++i ) {
560 botNode = dqDecodePtr( dq->bottom );
561 botIndx = dqDecodeIdx( dq->bottom );
563 topNode = dqDecodePtr( dq->top );
564 topIndx = dqDecodeIdx( dq->top );
568 // check all the relevant indices of this
569 // node in the deque, noting if we are in
570 // the top/bottom node which can be partially
572 if( n == botNode ) { jLo = botIndx; } else { jLo = 0; }
573 if( n == topNode ) { jHi = topIndx; } else { jHi = DQNODE_ARRAYSIZE; }
575 for( j = jLo; j < jHi; ++j ) {
577 //SESEcommon* common = (SESEcommon*) n->itsDataArr[j];
578 //if(common==seseCommon){
579 // skip the current running SESE
583 SESEcommon* seseRec = (SESEcommon*) n->itsDataArr[j];
584 struct garbagelist* gl = (struct garbagelist*) &(seseRec[1]);
585 struct garbagelist* glroot = gl;
587 updateAscendantSESE( seseRec );
589 while( gl != NULL ) {
591 for( k = 0; k < gl->size; k++ ) {
592 void* orig = gl->array[k];
593 ENQUEUE( orig, gl->array[k] );
599 // we only have to move across the nodes
600 // of the deque if the top and bottom are
601 // not the same already
602 if( botNode != topNode ) {
605 } while( n != topNode );
613 void * ptr=dequeue();
615 int type=((int *)cpy)[0];
616 unsigned INTPTR * pointer;
620 /* Nothing is inside */
625 pointer=pointerarray[type];
627 /* Array of primitives */
629 #if defined(DSTM)||defined(FASTCHECK)
630 struct ArrayObject *ao=(struct ArrayObject *) ptr;
631 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
632 ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
633 ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
636 struct ArrayObject *ao=(struct ArrayObject *) ptr;
637 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
638 SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
640 } else if (((INTPTR)pointer)==1) {
641 /* Array of pointers */
642 struct ArrayObject *ao=(struct ArrayObject *) ptr;
643 struct ArrayObject *ao_cpy=(struct ArrayObject *) cpy;
644 #if (defined(DSTM)||defined(FASTCHECK))
645 ENQUEUE((void *)ao->___nextobject___, *((void **)&ao_cpy->___nextobject___));
646 ENQUEUE((void *)ao->___localcopy___, *((void **)&ao_cpy->___localcopy___));
649 SENQUEUE((void *)ao->___objlocation___, *((void **)&ao_cpy->___objlocation___));
651 int length=ao->___length___;
653 for(i=0; i<length; i++) {
654 void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
655 ENQUEUE(objptr, ((void **)(((char *)&ao_cpy->___length___)+sizeof(int)))[i]);
658 INTPTR size=pointer[0];
660 for(i=1; i<=size; i++) {
661 unsigned int offset=pointer[i];
662 void * objptr=*((void **)(((char *)ptr)+offset));
663 ENQUEUE(objptr, *((void **)(((char *)cpy)+offset)));
673 //rehash memory queues of current running SESEs
674 struct listitem *listptr=list;
675 while(listptr!=NULL){
676 rehashMemoryQueue((SESEcommon*)(listptr->seseCommon));
677 listptr=listptr->next;
682 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
684 pthread_mutex_unlock(&gclistlock);
689 /* Fix up the references from tags. This can't be done earlier,
690 because we don't want tags to keep objects alive */
692 while(taghead!=NULL) {
694 struct pointerblock *tmp=taghead->next;
695 for(i=0; i<tagindex; i++) {
696 struct ___TagDescriptor___ *tagd=taghead->ptrs[i];
697 struct ___Object___ *obj=tagd->flagptr;
698 struct ___TagDescriptor___ *copy=((struct ___TagDescriptor___**)tagd)[1];
700 /* Zero object case */
701 } else if (obj->type==-1) {
702 /* Single object case */
703 copy->flagptr=((struct ___Object___**)obj)[1];
704 } else if (obj->type==OBJECTARRAYTYPE) {
706 struct ArrayObject *ao=(struct ArrayObject *) obj;
710 struct ArrayObject *aonew;
712 /* Count live objects */
713 for(j=0; j<ao->___cachedCode___; j++) {
714 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
719 livecount=((livecount-1)/OBJECTARRAYINTERVAL+1)*OBJECTARRAYINTERVAL;
720 aonew=(struct ArrayObject *) tomalloc(sizeof(struct ArrayObject)+sizeof(struct ___Object___*)*livecount);
721 memcpy(aonew, ao, sizeof(struct ArrayObject));
722 aonew->type=OBJECTARRAYTYPE;
723 aonew->___length___=livecount;
725 for(j=0; j<ao->___cachedCode___; j++) {
726 struct ___Object___ * tobj=ARRAYGET(ao, struct ___Object___ *, j);
727 if (tobj->type==-1) {
728 struct ___Object___ * tobjcpy=((struct ___Object___**)tobj)[1];
729 ARRAYSET(aonew, struct ___Object___*, k++,tobjcpy);
732 aonew->___cachedCode___=k;
733 for(; k<livecount; k++) {
734 ARRAYSET(aonew, struct ___Object___*, k, NULL);
737 /* No object live anymore */
748 void * tomalloc(int size) {
749 void * ptr=to_heapptr;
756 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
757 void checkcollect(void * ptr) {
758 stopforgc((struct garbagelist *)ptr);
763 void checkcollect2(void * ptr) {
764 int ptrarray[]={1, (int)ptr, (int) revertlist};
765 stopforgc((struct garbagelist *)ptrarray);
767 revertlist=(struct ___Object___*)ptrarray[2];
771 void stopforgc(struct garbagelist * ptr) {
773 //just append us to the list
775 ptr=(struct garbagelist *) &ptrstack;
776 #if defined(STMARRAY)&&!defined(DUALVIEW)
778 ptr=(struct garbagelist *) &arraystack;
784 litem.locklist=pthread_getspecific(threadlocks);
786 #if defined(STM)||defined(THREADS)||defined(MLP)
787 litem.base=&memorybase;
790 litem.tc_size=c_size;
791 litem.tc_table=&c_table;
792 litem.tc_list=&c_list;
793 litem.tc_structs=&c_structs;
794 litem.objlist=newobjs;
796 litem.lockedlist=lockedobjs;
801 struct listitem *litem=pthread_getspecific(litemkey);
804 litem->locklist=pthread_getspecific(threadlocks);
807 pthread_mutex_lock(&gclistlock);
809 if ((listcount+1)==threadcount) {
810 //only do wakeup if we are ready to GC
811 pthread_cond_signal(&gccond);
813 pthread_mutex_unlock(&gclistlock);
816 void restartaftergc() {
818 pthread_mutex_lock(&gclock); // Wait for GC
819 pthread_mutex_unlock(&gclock);
821 pthread_mutex_lock(&gclistlock);
823 pthread_mutex_unlock(&gclistlock);
827 #if defined(STM)||defined(THREADS)||defined(MLP)
828 #define MEMORYBLOCK 65536
829 void * helper(struct garbagelist *, int);
830 void * mygcmalloc(struct garbagelist * stackptr, int size) {
833 if (memorybase==NULL||size>(memorytop-memorybase)) {
834 int toallocate=(size>MEMORYBLOCK)?size:MEMORYBLOCK;
835 memorybase=helper(stackptr, toallocate);
836 bzero(memorybase, toallocate);
837 memorytop=memorybase+toallocate;
839 char *retvalue=memorybase;
844 void * helper(struct garbagelist * stackptr, int size) {
846 void * mygcmalloc(struct garbagelist * stackptr, int size) {
849 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
850 while (pthread_mutex_trylock(&gclock)!=0) {
859 if (curr_heapptr>curr_heapgcpoint||curr_heapptr<curr_heapbase) {
860 if (curr_heapbase==0) {
861 /* Need to allocate base heap */
862 curr_heapbase=malloc(INITIALHEAPSIZE);
863 if (curr_heapbase==NULL) {
864 printf("malloc failed. Garbage colletcor couldn't get enough memory. Try changing heap size.\n");
867 #if defined(STM)||defined(THREADS)||defined(MLP)
869 bzero(curr_heapbase, INITIALHEAPSIZE);
871 curr_heaptop=curr_heapbase+INITIALHEAPSIZE;
872 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(INITIALHEAPSIZE);
873 curr_heapptr=curr_heapbase+size;
875 to_heapbase=malloc(INITIALHEAPSIZE);
876 if (to_heapbase==NULL) {
877 printf("malloc failed. Garbage collector couldn't get enough memory. Try changing heap size.\n");
881 to_heaptop=to_heapbase+INITIALHEAPSIZE;
882 to_heapptr=to_heapbase;
884 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
885 pthread_mutex_unlock(&gclock);
890 /* Grow the to heap if necessary */
892 INTPTR curr_heapsize=curr_heaptop-curr_heapbase;
893 INTPTR to_heapsize=to_heaptop-to_heapbase;
894 INTPTR last_heapsize=0;
896 last_heapsize=HEAPSIZE(lastgcsize, size);
897 if ((last_heapsize&7)!=0)
898 last_heapsize+=(8-(last_heapsize%8));
900 if (curr_heapsize>last_heapsize)
901 last_heapsize=curr_heapsize;
902 if (last_heapsize>to_heapsize) {
904 to_heapbase=malloc(last_heapsize);
905 if (to_heapbase==NULL) {
906 printf("Error Allocating enough memory\n");
909 to_heaptop=to_heapbase+last_heapsize;
910 to_heapptr=to_heapbase;
914 /* Do our collection */
917 /* Update stat on previous gc size */
918 lastgcsize=(to_heapptr-to_heapbase)+size;
921 printf("Garbage collected: Old bytes: %u\n", curr_heapptr-curr_heapbase);
922 printf("New space: %u\n", to_heapptr-to_heapbase);
923 printf("Total space: %u\n", to_heaptop-to_heapbase);
926 for(i=0;i<MAXSTATS;i++) {
927 if (garbagearray[i]!=0)
928 printf("Type=%d Size=%u\n", i, garbagearray[i]);
932 /* Flip to/curr heaps */
934 void * tmp=to_heapbase;
935 to_heapbase=curr_heapbase;
939 to_heaptop=curr_heaptop;
943 curr_heapptr=to_heapptr+size;
944 curr_heapgcpoint=((char *) curr_heapbase)+GCPOINT(curr_heaptop-curr_heapbase);
945 to_heapptr=to_heapbase;
947 /* Not enough room :(, redo gc */
948 if (curr_heapptr>curr_heapgcpoint) {
949 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
950 pthread_mutex_unlock(&gclock);
952 return mygcmalloc(stackptr, size);
955 bzero(tmp, curr_heaptop-tmp);
956 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
957 pthread_mutex_unlock(&gclock);
962 #if defined(THREADS)||defined(DSTM)||defined(STM)||defined(MLP)
963 pthread_mutex_unlock(&gclock);
969 int gc_createcopy(void * orig, void ** copy_ptr) {
974 int type=((int *)orig)[0];
976 *copy_ptr=((void **)orig)[1];
979 if (type<NUMCLASSES) {
980 /* We have a normal object */
982 int size=classsize[type]+sizeof(objheader_t);
983 void *newobj=tomalloc(size);
984 memcpy(newobj,((char *) orig)-sizeof(objheader_t), size);
985 newobj=((char *)newobj)+sizeof(objheader_t);
987 int size=classsize[type];
988 void *newobj=tomalloc(size);
989 memcpy(newobj, orig, size);
992 garbagearray[type]+=size;
995 ((void **)orig)[1]=newobj;
999 /* We have an array */
1000 struct ArrayObject *ao=(struct ArrayObject *)orig;
1001 int elementsize=classsize[type];
1002 int length=ao->___length___;
1005 int basesize=length*elementsize;
1006 basesize=(basesize+LOWMASK)&HIGHMASK;
1007 int versionspace=sizeof(int)*2*(basesize>>INDEXSHIFT);
1008 int size=sizeof(struct ArrayObject)+basesize+sizeof(objheader_t)+versionspace;
1009 void *newobj=tomalloc(size);
1010 memcpy(newobj, ((char*)orig)-sizeof(objheader_t)-versionspace, size);
1011 newobj=((char *)newobj)+sizeof(objheader_t)+versionspace;
1013 int size=sizeof(struct ArrayObject)+length*elementsize+sizeof(objheader_t);
1014 void *newobj=tomalloc(size);
1015 memcpy(newobj, ((char*)orig)-sizeof(objheader_t), size);
1016 newobj=((char *)newobj)+sizeof(objheader_t);
1019 int size=sizeof(struct ArrayObject)+length*elementsize;
1020 void *newobj=tomalloc(size);
1021 memcpy(newobj, orig, size);
1024 garbagearray[type]+=size;
1026 ((int *)orig)[0]=-1;
1027 ((void **)orig)[1]=newobj;
1035 updateForwardList(struct Queue *forwardList, int prevUpdate){
1037 struct QueueItem * fqItem=getHead(forwardList);
1038 while(fqItem!=NULL){
1039 SESEcommon* seseRec = (SESEcommon*)(fqItem->objectptr);
1040 struct garbagelist * gl=(struct garbagelist *)&(seseRec[1]);
1041 if(prevUpdate==TRUE){
1042 updateAscendantSESE(seseRec);
1044 // do something here
1047 for(i=0; i<gl->size; i++) {
1048 void * orig=gl->array[i];
1049 ENQUEUE(orig, gl->array[i]);
1053 // iterate forwarding list of seseRec
1054 struct Queue* fList=&seseRec->forwardList;
1055 updateForwardList(fList,prevUpdate);
1056 fqItem=getNextQueueItem(fqItem);
1061 updateMemoryQueue(SESEcommon* seseParent){
1062 // update memory queue
1064 for(i=0; i<seseParent->numMemoryQueue; i++){
1065 MemoryQueue *memoryQueue=seseParent->memoryQueueArray[i];
1066 MemoryQueueItem *memoryItem=memoryQueue->head;
1067 while(memoryItem!=NULL){
1068 if(memoryItem->type==HASHTABLE){
1069 Hashtable *ht=(Hashtable*)memoryItem;
1070 for(binidx=0; binidx<NUMBINS; binidx++){
1071 BinElement *bin=ht->array[binidx];
1072 BinItem *binItem=bin->head;
1073 while(binItem!=NULL){
1074 if(binItem->type==READBIN){
1075 ReadBinItem* readBinItem=(ReadBinItem*)binItem;
1077 for(ridx=0; ridx<readBinItem->index; ridx++){
1078 REntry *rentry=readBinItem->array[ridx];
1079 SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1080 struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1081 updateAscendantSESE(seseRec);
1084 for(i=0; i<gl->size; i++) {
1085 void * orig=gl->array[i];
1086 ENQUEUE(orig, gl->array[i]);
1092 REntry *rentry=((WriteBinItem*)binItem)->val;
1093 SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1094 struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1095 updateAscendantSESE(seseRec);
1098 for(i=0; i<gl->size; i++) {
1099 void * orig=gl->array[i];
1100 ENQUEUE(orig, gl->array[i]);
1105 binItem=binItem->next;
1108 }else if(memoryItem->type==VECTOR){
1109 Vector *vt=(Vector*)memoryItem;
1111 for(idx=0; idx<vt->index; idx++){
1112 REntry *rentry=vt->array[idx];
1114 SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1115 struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1116 updateAscendantSESE(seseRec);
1119 for(i=0; i<gl->size; i++) {
1120 void * orig=gl->array[i];
1121 ENQUEUE(orig, gl->array[i]);
1127 }else if(memoryItem->type==SINGLEITEM){
1128 SCC *scc=(SCC*)memoryItem;
1129 REntry *rentry=scc->val;
1131 SESEcommon* seseRec = (SESEcommon*)(rentry->seseRec);
1132 struct garbagelist * gl= (struct garbagelist *)&(seseRec[1]);
1133 updateAscendantSESE(seseRec);
1136 for(i=0; i<gl->size; i++) {
1137 void * orig=gl->array[i];
1138 ENQUEUE(orig, gl->array[i]);
1144 memoryItem=memoryItem->next;
1149 updateAscendantSESE(SESEcommon* seseRec){
1151 for(prevIdx=0; prevIdx<(seseRec->numDependentSESErecords); prevIdx++){
1152 SESEcommon* prevSESE = (SESEcommon*)
1155 seseRec->offsetToDepSESErecords +
1156 (sizeof(INTPTR)*prevIdx)
1160 struct garbagelist * prevgl=(struct garbagelist *)&(((SESEcommon*)(prevSESE))[1]);
1161 while(prevgl!=NULL) {
1163 for(i=0; i<prevgl->size; i++) {
1164 void * orig=prevgl->array[i];
1165 ENQUEUE(orig, prevgl->array[i]);
1167 prevgl=prevgl->next;
1175 int within(void *ptr){ //debug function
1176 if(ptr>curr_heapptr || ptr<curr_heapbase){
1177 __asm__ __volatile__ ("int $3"); // breakpoint