3 #include "multicoregarbage.h"
4 #include "multicoreruntime.h"
5 #include "runtime_arch.h"
6 #include "SimpleHash.h"
7 #include "GenericHashtable.h"
8 #include "ObjectHash.h"
11 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
12 extern int numqueues[][NUMCLASSES];
14 extern struct genhashtable * activetasks;
15 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
16 extern struct taskparamdescriptor *currtpd;
20 struct pointerblock *next;
23 struct pointerblock *gchead=NULL;
25 struct pointerblock *gctail=NULL;
27 struct pointerblock *gctail2=NULL;
29 struct pointerblock *gcspare=NULL;
31 #define NUMLOBJPTRS 20
33 struct lobjpointerblock {
34 void * lobjs[NUMLOBJPTRS];
35 //void * dsts[NUMLOBJPTRS];
36 int lengths[NUMLOBJPTRS];
37 //void * origs[NUMLOBJPTRS];
38 int hosts[NUMLOBJPTRS];
39 struct lobjpointerblock *next;
42 struct lobjpointerblock *gclobjhead=NULL;
43 int gclobjheadindex=0;
44 struct lobjpointerblock *gclobjtail=NULL;
45 int gclobjtailindex=0;
46 struct lobjpointerblock *gclobjtail2=NULL;
47 int gclobjtailindex2=0;
48 struct lobjpointerblock *gclobjspare=NULL;
51 inline void dumpSMem() {
58 tprintf("Dump shared mem: \n");
59 tprintf("++++ reserved sblocks ++++ \n");
60 for(i=BAMBOO_BASE_VA; i<gcbaseva; i+= 4*16) {
61 tprintf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",
62 *((int *)(i)), *((int *)(i + 4)), *((int *)(i + 4*2)), *((int *)(i + 4*3)),
63 *((int *)(i + 4*4)), *((int *)(i + 4*5)), *((int *)(i + 4*6)), *((int *)(i + 4*7)),
64 *((int *)(i + 4*8)), *((int *)(i + 4*9)), *((int *)(i + 4*10)), *((int *)(i + 4*11)),
65 *((int *)(i + 4*12)), *((int *)(i + 4*13)), *((int *)(i + 4*14)), *((int *)(i + 4*15)));
67 for(i=gcbaseva;i<BAMBOO_BASE_VA+BAMBOO_SHARED_MEM_SIZE;i+=4*16){
68 if(j%((BAMBOO_SMEM_SIZE)/(4*16)) == 0) {
69 if(j < ((BAMBOO_LARGE_SMEM_BOUND)/(4*16))) {
70 if((j > 0) && (j%((BAMBOO_SMEM_SIZE_L)/(4*16)) == 0)) {
72 if(block%NUMCORES == 0) {
84 if(block%NUMCORES == 0) {
94 tprintf("==== %d, %d : core %d, saddr %x====\n", block,
95 sblock++, coren, sblock*(BAMBOO_SMEM_SIZE)+BAMBOO_BASE_VA);
98 tprintf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x \n",
99 *((int *)(i)), *((int *)(i + 4)), *((int *)(i + 4*2)), *((int *)(i + 4*3)),
100 *((int *)(i + 4*4)), *((int *)(i + 4*5)), *((int *)(i + 4*6)), *((int *)(i + 4*7)),
101 *((int *)(i + 4*8)), *((int *)(i + 4*9)), *((int *)(i + 4*10)), *((int *)(i + 4*11)),
102 *((int *)(i + 4*12)), *((int *)(i + 4*13)), *((int *)(i + 4*14)), *((int *)(i + 4*15)));
108 // should be invoked with interruption closed
109 inline void gc_enqueue_I(void *ptr) {
111 BAMBOO_DEBUGPRINT(0xe601);
112 BAMBOO_DEBUGPRINT_REG(ptr);
114 if (gcheadindex==NUMPTRS) {
115 struct pointerblock * tmp;
120 tmp=RUNMALLOC_I(sizeof(struct pointerblock));
121 } // if (gcspare!=NULL)
125 } // if (gcheadindex==NUMPTRS)
126 gchead->ptrs[gcheadindex++]=ptr;
128 BAMBOO_DEBUGPRINT(0xe602);
130 } // void gc_enqueue_I(void *ptr)
132 // dequeue and destroy the queue
133 inline void * gc_dequeue() {
134 if (gctailindex==NUMPTRS) {
135 struct pointerblock *tmp=gctail;
142 } // if (gcspare!=NULL)
143 } // if (gctailindex==NUMPTRS)
144 return gctail->ptrs[gctailindex++];
145 } // void * gc_dequeue()
147 // dequeue and do not destroy the queue
148 inline void * gc_dequeue2() {
149 if (gctailindex2==NUMPTRS) {
150 struct pointerblock *tmp=gctail2;
151 gctail2=gctail2->next;
153 } // if (gctailindex2==NUMPTRS)
154 return gctail2->ptrs[gctailindex2++];
155 } // void * gc_dequeue2()
157 inline int gc_moreItems() {
158 if ((gchead==gctail)&&(gctailindex==gcheadindex))
161 } // int gc_moreItems()
163 inline int gc_moreItems2() {
164 if ((gchead==gctail2)&&(gctailindex2==gcheadindex))
167 } // int gc_moreItems2()
169 // should be invoked with interruption closed
170 // enqueue a large obj: start addr & length
171 inline void gc_lobjenqueue_I(void *ptr,
175 BAMBOO_DEBUGPRINT(0xe901);
177 if (gclobjheadindex==NUMLOBJPTRS) {
178 struct lobjpointerblock * tmp;
179 if (gclobjspare!=NULL) {
183 tmp=RUNMALLOC_I(sizeof(struct lobjpointerblock));
184 } // if (gclobjspare!=NULL)
185 gclobjhead->next=tmp;
188 } // if (gclobjheadindex==NUMLOBJPTRS)
189 gclobjhead->lobjs[gclobjheadindex]=ptr;
190 gclobjhead->lengths[gclobjheadindex]=length;
191 gclobjhead->hosts[gclobjheadindex++]=host;
193 BAMBOO_DEBUGPRINT_REG(gclobjhead->lobjs[gclobjheadindex-1]);
194 BAMBOO_DEBUGPRINT_REG(gclobjhead->lengths[gclobjheadindex-1]);
195 BAMBOO_DEBUGPRINT_REG(gclobjhead->hosts[gclobjheadindex-1]);
197 } // void gc_lobjenqueue_I(void *ptr...)
199 // dequeue and destroy the queue
200 inline void * gc_lobjdequeue(int * length,
202 if (gclobjtailindex==NUMLOBJPTRS) {
203 struct lobjpointerblock *tmp=gclobjtail;
204 gclobjtail=gclobjtail->next;
206 if (gclobjspare!=NULL) {
210 } // if (gclobjspare!=NULL)
211 } // if (gclobjtailindex==NUMLOBJPTRS)
213 *length = gclobjtail->lengths[gclobjtailindex];
216 *host = (int)(gclobjtail->hosts[gclobjtailindex]);
218 return gclobjtail->lobjs[gclobjtailindex++];
219 } // void * gc_lobjdequeue()
221 inline int gc_lobjmoreItems() {
222 if ((gclobjhead==gclobjtail)&&(gclobjtailindex==gclobjheadindex))
225 } // int gc_lobjmoreItems()
227 // dequeue and don't destroy the queue
228 inline void gc_lobjdequeue2() {
229 if (gclobjtailindex2==NUMLOBJPTRS) {
230 gclobjtail2=gclobjtail2->next;
234 }// if (gclobjtailindex2==NUMLOBJPTRS)
235 } // void * gc_lobjdequeue2()
237 inline int gc_lobjmoreItems2() {
238 if ((gclobjhead==gclobjtail2)&&(gclobjtailindex2==gclobjheadindex))
241 } // int gc_lobjmoreItems2()
243 INTPTR gccurr_heapbound = 0;
245 inline void gettype_size(void * ptr,
248 int type = ((int *)ptr)[0];
250 if(type < NUMCLASSES) {
252 size = classsize[type];
255 struct ArrayObject *ao=(struct ArrayObject *)ptr;
256 int elementsize=classsize[type];
257 int length=ao->___length___;
258 size=sizeof(struct ArrayObject)+length*elementsize;
259 } // if(type < NUMCLASSES)
264 inline bool isLarge(void * ptr,
268 BAMBOO_DEBUGPRINT(0xe701);
269 BAMBOO_DEBUGPRINT_REG(ptr);
271 // check if a pointer is referring to a large object
272 gettype_size(ptr, ttype, tsize);
274 BAMBOO_DEBUGPRINT(*tsize);
276 int bound = (BAMBOO_SMEM_SIZE);
277 if(((int)ptr-gcbaseva) < (BAMBOO_LARGE_SMEM_BOUND)) {
278 bound = (BAMBOO_SMEM_SIZE_L);
280 if((((int)ptr-gcbaseva)%(bound))==0) {
281 // ptr is a start of a block
283 BAMBOO_DEBUGPRINT(0xe702);
284 BAMBOO_DEBUGPRINT(1);
288 if((bound-(((int)ptr-gcbaseva)%bound)) < (*tsize)) {
289 // it acrosses the boundary of current block
291 BAMBOO_DEBUGPRINT(0xe703);
292 BAMBOO_DEBUGPRINT(1);
297 BAMBOO_DEBUGPRINT(0);
300 } // bool isLarge(void * ptr, int * ttype, int * tsize)
302 inline int hostcore(void * ptr) {
303 // check the host core of ptr
307 RESIDECORE(ptr, &x, &y);
308 host = (x==0)?(x*bamboo_height+y):(x*bamboo_height+y-2);
310 } // int hostcore(void * ptr)
312 inline bool isLocal(void * ptr) {
313 // check if a pointer is in shared heap on this core
314 return hostcore(ptr) == BAMBOO_NUM_OF_CORE;
315 } // bool isLocal(void * ptr)
317 inline bool gc_checkCoreStatus() {
318 bool allStall = true;
319 for(int i = 0; i < NUMCORES; ++i) {
320 if(gccorestatus[i] != 0) {
323 } // if(gccorestatus[i] != 0)
324 } // for(i = 0; i < NUMCORES; ++i)
328 inline void checkMarkStatue() {
330 BAMBOO_DEBUGPRINT(0xee01);
334 (waitconfirm && (numconfirm == 0))) {
336 BAMBOO_DEBUGPRINT(0xee02);
338 BAMBOO_START_CRITICAL_SECTION_STATUS();
339 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
340 gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
341 gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
342 // check the status of all cores
343 bool allStall = gc_checkCoreStatus();
345 BAMBOO_DEBUGPRINT(0xee03);
349 BAMBOO_DEBUGPRINT(0xee04);
351 // check if the sum of send objs and receive obj are the same
352 // yes->check if the info is the latest; no->go on executing
354 for(i = 0; i < NUMCORES; ++i) {
355 sumsendobj += gcnumsendobjs[i];
356 } // for(i = 0; i < NUMCORES; ++i)
358 BAMBOO_DEBUGPRINT(0xee05);
359 BAMBOO_DEBUGPRINT_REG(sumsendobj);
361 for(i = 0; i < NUMCORES; ++i) {
362 sumsendobj -= gcnumreceiveobjs[i];
363 } // for(i = 0; i < NUMCORES; ++i)
365 BAMBOO_DEBUGPRINT(0xee06);
366 BAMBOO_DEBUGPRINT_REG(sumsendobj);
368 if(0 == sumsendobj) {
370 BAMBOO_DEBUGPRINT(0xee07);
374 BAMBOO_DEBUGPRINT(0xee08);
376 // the first time found all cores stall
377 // send out status confirm msg to all other cores
378 // reset the corestatus array too
379 gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
381 numconfirm = NUMCORES - 1;
382 for(i = 1; i < NUMCORES; ++i) {
384 // send mark phase finish confirm request msg to core i
385 send_msg_1(i, GCMARKCONFIRM);
386 } // for(i = 1; i < NUMCORES; ++i)
389 BAMBOO_DEBUGPRINT(0xee09);
391 // all the core status info are the latest
393 gcphase = COMPACTPHASE;
394 // restore the gcstatus for all cores
395 for(i = 0; i < NUMCORES; ++i) {
397 } // for(i = 0; i < NUMCORES; ++i)
398 } // if(!gcwautconfirm) else()
399 } // if(0 == sumsendobj)
401 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
402 } // if((!waitconfirm)...
404 BAMBOO_DEBUGPRINT(0xee0a);
406 } // void checkMarkStatue()
408 inline bool preGC() {
409 // preparation for gc
410 // make sure to clear all incoming msgs espacially transfer obj msgs
412 BAMBOO_DEBUGPRINT(0xec01);
416 (waitconfirm && (numconfirm == 0))) {
417 // send out status confirm msgs to all cores to check if there are
418 // transfer obj msgs on-the-fly
420 numconfirm = NUMCORES - 1;
421 for(i = 1; i < NUMCORES; ++i) {
423 // send status confirm msg to core i
424 send_msg_1(i, STATUSCONFIRM);
425 } // for(i = 1; i < NUMCORES; ++i)
428 BAMBOO_DEBUGPRINT(0xec02);
430 while(numconfirm != 0) {} // wait for confirmations
434 BAMBOO_DEBUGPRINT(0xec03);
436 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
437 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
440 BAMBOO_DEBUGPRINT(0xec04);
442 for(i = 0; i < NUMCORES; ++i) {
443 sumsendobj += numsendobjs[i];
445 BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
447 } // for(i = 1; i < NUMCORES; ++i)
449 BAMBOO_DEBUGPRINT(0xec05);
450 BAMBOO_DEBUGPRINT_REG(sumsendobj);
452 for(i = 0; i < NUMCORES; ++i) {
453 sumsendobj -= numreceiveobjs[i];
455 BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
457 } // for(i = 1; i < NUMCORES; ++i)
459 BAMBOO_DEBUGPRINT(0xec06);
460 BAMBOO_DEBUGPRINT_REG(sumsendobj);
462 if(0 == sumsendobj) {
465 // still have some transfer obj msgs on-the-fly, can not start gc
467 } // if(0 == sumsendobj)
470 BAMBOO_DEBUGPRINT(0xec07);
472 // previously asked for status confirmation and do not have all the
473 // confirmations yet, can not start gc
475 } // if((!waitconfirm) ||
478 inline void initGC() {
480 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
481 for(i = 0; i < NUMCORES; ++i) {
483 gcnumsendobjs[i] = 0;
484 gcnumreceiveobjs[i] = 0;
486 gcrequiredmems[i] = 0;
487 gcfilledblocks[i] = 0;
489 } // for(i = 0; i < NUMCORES; ++i)
494 gcself_numsendobjs = 0;
495 gcself_numreceiveobjs = 0;
496 gcmarkedptrbound = 0;
510 gcheadindex=gctailindex=gctailindex2 = 0;
511 gchead=gctail=gctail2=RUNMALLOC(sizeof(struct pointerblock));
513 gctailindex = gctailindex2 = gcheadindex;
514 gctail = gctail2 = gchead;
517 // initialize the large obj queues
518 if (gclobjhead==NULL) {
521 gclobjtailindex2 = 0;
522 gclobjhead=gclobjtail=gclobjtail2=
523 RUNMALLOC(sizeof(struct lobjpointerblock));
525 gclobjtailindex = gclobjtailindex2 = gclobjheadindex;
526 gclobjtail = gclobjtail2 = gclobjhead;
529 freeRuntimeHash(gcpointertbl);
530 gcpointertbl = allocateRuntimeHash(20);
533 // compute load balance for all cores
534 inline int loadbalance() {
535 // compute load balance
538 // get the total loads
539 int tloads = gcloads[STARTUPCORE];
540 for(i = 1; i < NUMCORES; i++) {
541 tloads += gcloads[i];
543 int heaptop = gcbaseva + tloads;
545 BAMBOO_DEBUGPRINT(0xdddd);
546 BAMBOO_DEBUGPRINT_REG(tloads);
547 BAMBOO_DEBUGPRINT_REG(heaptop);
550 BLOCKINDEX(heaptop, &b);
551 int numbpc = b / NUMCORES; // num of blocks per core
553 BAMBOO_DEBUGPRINT_REG(b);
554 BAMBOO_DEBUGPRINT_REG(numbpc);
556 gcheapdirection = (numbpc%2 == 0);
559 RESIDECORE(heaptop, &x, &y);
560 gctopcore = (x == 0 ? y : x * bamboo_height + y - 2);
562 BAMBOO_DEBUGPRINT_REG(gctopcore);
565 } // void loadbalance()
567 inline bool cacheLObjs() {
568 // check the total mem size need for large objs
572 BAMBOO_DEBUGPRINT(0xe801);
574 gclobjtail2 = gclobjtail;
575 gclobjtailindex2 = gclobjtailindex;
576 while(gc_lobjmoreItems2()){
578 size = gclobjtail2->lengths[gclobjtailindex2 - 1];
581 BAMBOO_DEBUGPRINT_REG(size);
582 BAMBOO_DEBUGPRINT_REG(sumsize);
584 } // while(gc_lobjmoreItems2())
586 // check if there are enough space to cache these large objs
587 INTPTR dst = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE) - sumsize;
588 if(gcheaptop > dst) {
589 // do not have enough room to cache large objs
593 BAMBOO_DEBUGPRINT(0xe802);
594 BAMBOO_DEBUGPRINT_REG(dst);
597 gcheaptop = dst; // Note: record the start of cached lobjs with gcheaptop
598 // cache the largeObjs to the top of the shared heap
599 gclobjtail2 = gclobjtail;
600 gclobjtailindex2 = gclobjtailindex;
601 while(gc_lobjmoreItems2()) {
603 size = gclobjtail2->lengths[gclobjtailindex2 - 1];
604 // set the mark field to 2, indicating that this obj has been moved and need to be flushed
605 ((int *)(gclobjtail2->lobjs[gclobjtailindex2-1]))[6] = 2;
606 memcpy(dst, gclobjtail2->lobjs[gclobjtailindex2 - 1], size);
609 BAMBOO_DEBUGPRINT_REG(gclobjtail2->lobjs[gclobjtailindex2-1]);
610 BAMBOO_DEBUGPRINT(dst-size);
611 BAMBOO_DEBUGPRINT_REG(size);
615 } // void cacheLObjs()
617 inline void moveLObjs() {
619 BAMBOO_DEBUGPRINT(0xea01);
621 // find current heap top
622 // flush all gcloads to indicate the real heap top on one core
623 // previous it represents the next available ptr on a core
624 if((gcloads[0] > (gcbaseva+(BAMBOO_SMEM_SIZE_L)))
625 && ((gcloads[0]%(BAMBOO_SMEM_SIZE)) == 0)) {
626 // edge of a block, check if this is exactly the heaptop
627 BASEPTR(0, gcfilledblocks[0]-1, &(gcloads[0]));
628 gcloads[0]+=(gcfilledblocks[0]>1?(BAMBOO_SMEM_SIZE):(BAMBOO_SMEM_SIZE_L));
630 int tmpheaptop = gcloads[0];
632 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
634 for(int i = 1; i < NUMCORES; i++) {
635 if((gcloads[i] > (gcbaseva+(BAMBOO_SMEM_SIZE_L)))
636 && ((gcloads[i] % (BAMBOO_SMEM_SIZE)) == 0)) {
637 // edge of a block, check if this is exactly the heaptop
638 BASEPTR(0, gcfilledblocks[i]-1, &gcloads[i]);
640 +=(gcfilledblocks[i]>1?(BAMBOO_SMEM_SIZE):(BAMBOO_SMEM_SIZE_L));
642 if(tmpheaptop < gcloads[i]) {
643 tmpheaptop = gcloads[i];
646 BAMBOO_DEBUGPRINT_REG(gcloads[i]);
647 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
650 // move large objs from gcheaptop to tmpheaptop
651 // write the header first
652 int tomove = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE) - gcheaptop;
654 BAMBOO_DEBUGPRINT(0xea02);
655 BAMBOO_DEBUGPRINT_REG(tomove);
657 // flush the sbstartbl
658 memset(&(gcsbstarttbl[gcreservedsb]), '\0',
659 BAMBOO_SHARED_MEM_SIZE/BAMBOO_SMEM_SIZE*sizeof(INTPTR));
661 gcheaptop = tmpheaptop;
664 // check how many blocks it acrosses
665 int remain = tmpheaptop-gcbaseva;
666 int b = remain/(BAMBOO_SMEM_SIZE) + gcreservedsb;
667 // check the remaining space in this block
668 int bound = (BAMBOO_SMEM_SIZE);
669 if(remain < (BAMBOO_LARGE_SMEM_BOUND)) {
670 bound = (BAMBOO_SMEM_SIZE_L);
672 remain = bound - remain%bound;
675 BAMBOO_DEBUGPRINT(0xea03);
681 int base = tmpheaptop;
683 remain -= BAMBOO_CACHE_LINE_SIZE;
684 tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
685 while(gc_lobjmoreItems()) {
686 ptr = (int)(gc_lobjdequeue(&size, &host));
687 ALIGNSIZE(size, &isize);
689 // this object acrosses blocks
691 // close current block, fill its header
692 memset(base, '\0', BAMBOO_CACHE_LINE_SIZE);
693 *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
697 remain = ((tmpheaptop-gcbaseva)<(BAMBOO_LARGE_SMEM_BOUND)) ?
698 BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
700 remain -= BAMBOO_CACHE_LINE_SIZE;
701 tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
704 // move the large obj
705 memcpy(tmpheaptop, gcheaptop, size);
706 // fill the remaining space with -2 padding
707 memset(tmpheaptop+size, -2, isize-size);
709 BAMBOO_DEBUGPRINT(0xea04);
710 BAMBOO_DEBUGPRINT_REG(gcheaptop);
711 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
712 BAMBOO_DEBUGPRINT_REG(size);
713 BAMBOO_DEBUGPRINT_REG(isize);
716 if(host == BAMBOO_NUM_OF_CORE) {
717 BAMBOO_START_CRITICAL_SECTION();
718 RuntimeHashadd_I(gcpointertbl, ptr, tmpheaptop);
719 BAMBOO_CLOSE_CRITICAL_SECTION();
721 BAMBOO_DEBUGPRINT(0xcdcd);
722 BAMBOO_DEBUGPRINT_REG(ptr);
723 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
726 // send the original host core with the mapping info
727 send_msg_3(host, GCLOBJMAPPING, ptr, tmpheaptop);
729 BAMBOO_DEBUGPRINT(0xcdcd);
730 BAMBOO_DEBUGPRINT_REG(ptr);
731 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
733 } // if(host == BAMBOO_NUM_OF_CORE) else ...
736 // set the gcsbstarttbl
737 int tmpsbs = 1+(isize-remain-1)/BAMBOO_SMEM_SIZE;
738 for(int k = 1; k < tmpsbs; k++) {
739 gcsbstarttbl[b+k] = (INTPTR)(-1);
742 if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) {
743 gcsbstarttbl[b] = (INTPTR)(-1);
744 remain = ((tmpheaptop-gcbaseva)<(BAMBOO_LARGE_SMEM_BOUND)) ?
745 BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
747 gcsbstarttbl[b] = (INTPTR)(tmpheaptop);
748 remain = tmpheaptop-gcbaseva;
749 int bound = remain<(BAMBOO_LARGE_SMEM_BOUND)?(BAMBOO_SMEM_SIZE_L):(BAMBOO_SMEM_SIZE);
750 remain = bound - remain%bound;
751 } // if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) else ...
753 // close current block and fill the header
754 memset(base, '\0', BAMBOO_CACHE_LINE_SIZE);
755 *((int*)base) = isize + BAMBOO_CACHE_LINE_SIZE;
758 remain -= BAMBOO_CACHE_LINE_SIZE;
759 tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
762 // move the large obj
763 memcpy(tmpheaptop, gcheaptop, size);
764 // fill the remaining space with -2 padding
765 memset(tmpheaptop+size, -2, isize-size);
767 BAMBOO_DEBUGPRINT(0xea05);
768 BAMBOO_DEBUGPRINT_REG(gcheaptop);
769 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
770 BAMBOO_DEBUGPRINT_REG(size);
771 BAMBOO_DEBUGPRINT_REG(isize);
775 if(host == BAMBOO_NUM_OF_CORE) {
776 BAMBOO_START_CRITICAL_SECTION();
777 RuntimeHashadd_I(gcpointertbl, ptr, tmpheaptop);
778 BAMBOO_CLOSE_CRITICAL_SECTION();
780 BAMBOO_DEBUGPRINT(0xcdcd);
781 BAMBOO_DEBUGPRINT_REG(ptr);
782 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
785 // send the original host core with the mapping info
786 send_msg_3(host, GCLOBJMAPPING, ptr, tmpheaptop);
788 BAMBOO_DEBUGPRINT(0xcdcd);
789 BAMBOO_DEBUGPRINT_REG(ptr);
790 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
792 } // if(host == BAMBOO_NUM_OF_CORE) else ...
794 } // if(remain < isize) else ...
795 } // while(gc_lobjmoreItems())
797 // close current block, fill the header
798 memset(base, '\0', BAMBOO_CACHE_LINE_SIZE);
799 *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
801 tmpheaptop -= BAMBOO_CACHE_LINE_SIZE;
803 gcheaptop = tmpheaptop;
805 BAMBOO_DEBUGPRINT(0xea06);
806 BAMBOO_DEBUGPRINT_REG(gcheaptop);
808 } // void moveLObjs()
810 inline void updateFreeMemList() {
811 struct freeMemItem * tochange = bamboo_free_mem_list->head;
812 if(tochange == NULL) {
813 bamboo_free_mem_list->head = tochange =
814 (struct freeMemItem *)RUNMALLOC(sizeof(struct freeMemItem));
816 // handle the top of the heap
817 tochange->ptr = gcheaptop;
818 tochange->size = BAMBOO_SHARED_MEM_SIZE + BAMBOO_BASE_VA - gcheaptop;
819 // zero out all these spare memory
820 memset(tochange->ptr, '\0', tochange->size);
821 if(bamboo_free_mem_list->tail != tochange) {
822 bamboo_free_mem_list->tail = tochange;
823 if(bamboo_free_mem_list->tail != NULL) {
824 RUNFREE(bamboo_free_mem_list->tail);
827 } // void updateFreeMemList()
830 inline void tomark(struct garbagelist * stackptr) {
831 if(MARKPHASE != gcphase) {
838 // enqueue current stack
839 while(stackptr!=NULL) {
841 BAMBOO_DEBUGPRINT(0xe501);
842 BAMBOO_DEBUGPRINT_REG(stackptr->size);
843 BAMBOO_DEBUGPRINT_REG(stackptr->next);
844 BAMBOO_DEBUGPRINT_REG(stackptr->array[0]);
846 for(i=0; i<stackptr->size; i++) {
847 if(stackptr->array[i] != NULL) {
848 BAMBOO_START_CRITICAL_SECTION();
849 gc_enqueue_I(stackptr->array[i]);
850 BAMBOO_CLOSE_CRITICAL_SECTION();
853 stackptr=stackptr->next;
857 BAMBOO_DEBUGPRINT(0xe503);
859 // enqueue objectsets
860 for(i=0; i<NUMCLASSES; i++) {
861 struct parameterwrapper ** queues =
862 objectqueues[BAMBOO_NUM_OF_CORE][i];
863 int length = numqueues[BAMBOO_NUM_OF_CORE][i];
864 for(j = 0; j < length; ++j) {
865 struct parameterwrapper * parameter = queues[j];
866 struct ObjectHash * set=parameter->objectset;
867 struct ObjectNode * ptr=set->listhead;
869 BAMBOO_START_CRITICAL_SECTION();
870 gc_enqueue_I((void *)ptr->key);
871 BAMBOO_CLOSE_CRITICAL_SECTION();
877 // euqueue current task descriptor
878 if(currtpd != NULL) {
880 BAMBOO_DEBUGPRINT(0xe504);
882 for(i=0; i<currtpd->numParameters; i++) {
883 BAMBOO_START_CRITICAL_SECTION();
884 gc_enqueue_I(currtpd->parameterArray[i]);
885 BAMBOO_CLOSE_CRITICAL_SECTION();
890 BAMBOO_DEBUGPRINT(0xe505);
892 // euqueue active tasks
893 struct genpointerlist * ptr=activetasks->list;
895 struct taskparamdescriptor *tpd=ptr->src;
897 for(i=0; i<tpd->numParameters; i++) {
898 BAMBOO_START_CRITICAL_SECTION();
899 gc_enqueue_I(tpd->parameterArray[i]);
900 BAMBOO_CLOSE_CRITICAL_SECTION();
906 BAMBOO_DEBUGPRINT(0xe506);
908 // enqueue cached transferred obj
909 struct QueueItem * tmpobjptr = getHead(&objqueue);
910 while(tmpobjptr != NULL) {
911 struct transObjInfo * objInfo =
912 (struct transObjInfo *)(tmpobjptr->objectptr);
913 BAMBOO_START_CRITICAL_SECTION();
914 gc_enqueue_I(objInfo->objptr);
915 BAMBOO_CLOSE_CRITICAL_SECTION();
916 tmpobjptr = getNextQueueItem(tmpobjptr);
920 BAMBOO_DEBUGPRINT(0xe507);
922 // enqueue cached objs to be transferred
923 struct QueueItem * item = getHead(totransobjqueue);
924 while(item != NULL) {
925 struct transObjInfo * totransobj =
926 (struct transObjInfo *)(item->objectptr);
927 BAMBOO_START_CRITICAL_SECTION();
928 gc_enqueue_I(totransobj->objptr);
929 BAMBOO_CLOSE_CRITICAL_SECTION();
930 item = getNextQueueItem(item);
931 } // while(item != NULL)
932 } // void tomark(struct garbagelist * stackptr)
934 inline void markObj(void * objptr) {
938 if(ISSHAREDOBJ(objptr)) {
939 int host = hostcore(objptr);
940 if(BAMBOO_NUM_OF_CORE == host) {
942 BAMBOO_START_CRITICAL_SECTION();
943 gc_enqueue_I(objptr);
944 BAMBOO_CLOSE_CRITICAL_SECTION();
947 BAMBOO_DEBUGPRINT(0xbbbb);
948 BAMBOO_DEBUGPRINT_REG(host);
949 BAMBOO_DEBUGPRINT_REG(objptr);
951 // send a msg to host informing that objptr is active
952 send_msg_2(host, GCMARKEDOBJ, objptr);
953 gcself_numsendobjs++;
956 BAMBOO_START_CRITICAL_SECTION();
957 gc_enqueue_I(objptr);
958 BAMBOO_CLOSE_CRITICAL_SECTION();
959 } // if(ISSHAREDOBJ(objptr))
960 } // void markObj(void * objptr)
962 inline void mark(bool isfirst,
963 struct garbagelist * stackptr) {
965 BAMBOO_DEBUGPRINT(0xed01);
969 BAMBOO_DEBUGPRINT(0xed02);
973 gccurr_heaptop = 0; // record the size of all active objs in this core
974 // aligned but does not consider block boundaries
975 gcmarkedptrbound = 0;
978 BAMBOO_DEBUGPRINT(0xed03);
981 bool checkfield = true;
982 bool sendStall = false;
984 while(MARKPHASE == gcphase) {
986 BAMBOO_DEBUGPRINT(0xed04);
988 while(gc_moreItems2()) {
990 BAMBOO_DEBUGPRINT(0xed05);
995 void * ptr = gc_dequeue2();
997 BAMBOO_DEBUGPRINT_REG(ptr);
1002 // check if it is a shared obj
1003 if(ISSHAREDOBJ(ptr)) {
1004 // a shared obj, check if it is a local obj on this core
1005 if(isLarge(ptr, &type, &size)) {
1006 // ptr is a large object
1007 if(((int *)ptr)[6] == 0) {
1008 // not marked and not enqueued
1009 BAMBOO_START_CRITICAL_SECTION();
1010 gc_lobjenqueue_I(ptr, size, BAMBOO_NUM_OF_CORE);
1012 BAMBOO_CLOSE_CRITICAL_SECTION();
1014 ((int *)ptr)[6] = 1;
1017 bool islocal = isLocal(ptr);
1018 if (islocal && (((int *)ptr)[6] == 0)) {
1019 // ptr is an unmarked active object on this core
1020 ALIGNSIZE(size, &isize);
1021 gccurr_heaptop += isize;
1023 BAMBOO_DEBUGPRINT(0xaaaa);
1024 BAMBOO_DEBUGPRINT_REG(ptr);
1025 BAMBOO_DEBUGPRINT_REG(isize);
1028 ((int *)ptr)[6] = 1;
1029 if(ptr + size > gcmarkedptrbound) {
1030 gcmarkedptrbound = ptr + size;
1031 } // if(ptr + size > gcmarkedptrbound)
1032 } else if ((!islocal) && (((int *)ptr)[6] == 0)) {
1033 int host = hostcore(ptr);
1035 BAMBOO_DEBUGPRINT(0xbbbb);
1036 BAMBOO_DEBUGPRINT_REG(host);
1037 BAMBOO_DEBUGPRINT_REG(ptr);
1039 // send a msg to host informing that ptr is active
1040 send_msg_2(host, GCMARKEDOBJ, ptr);
1041 gcself_numsendobjs++;
1043 }// if(isLocal(ptr)) else ...
1044 } // if(isLarge(ptr, &type, &size)) else ...
1045 } // if(ISSHAREDOBJ(ptr))
1047 BAMBOO_DEBUGPRINT(0xed06);
1051 // scan all pointers in ptr
1052 unsigned INTPTR * pointer;
1053 pointer=pointerarray[type];
1055 /* Array of primitives */
1057 } else if (((INTPTR)pointer)==1) {
1058 /* Array of pointers */
1059 struct ArrayObject *ao=(struct ArrayObject *) ptr;
1060 int length=ao->___length___;
1062 for(j=0; j<length; j++) {
1064 ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
1068 INTPTR size=pointer[0];
1070 for(i=1; i<=size; i++) {
1071 unsigned int offset=pointer[i];
1072 void * objptr=*((void **)(((char *)ptr)+offset));
1075 } // if (pointer==0) else if ... else ...
1077 } // while(!isEmpty(gctomark))
1079 BAMBOO_DEBUGPRINT(0xed07);
1081 gcbusystatus = false;
1082 // send mark finish msg to core coordinator
1083 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1085 BAMBOO_DEBUGPRINT(0xed08);
1087 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1088 gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
1089 gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
1090 gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
1094 BAMBOO_DEBUGPRINT(0xed09);
1096 send_msg_4(STARTUPCORE, GCFINISHMARK, BAMBOO_NUM_OF_CORE,
1097 gcself_numsendobjs, gcself_numreceiveobjs);
1102 BAMBOO_DEBUGPRINT(0xed0a);
1105 if(BAMBOO_NUM_OF_CORE == 0) {
1107 BAMBOO_DEBUGPRINT(0xed0b);
1111 } // while(MARKPHASE == gcphase)
1114 inline void compact2Heaptop() {
1115 // no cores with spare mem and some cores are blocked with pending move
1116 // find the current heap top and make them move to the heap top
1118 int numblocks = gcfilledblocks[gctopcore];
1119 BASEPTR(gctopcore, numblocks, &p);
1122 int remain = b<NUMCORES ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1123 /*if((gctopcore == STARTUPCORE) && (b == 0)) {
1124 remain -= gcreservedsb*BAMBOO_SMEM_SIZE;
1125 p += gcreservedsb*BAMBOO_SMEM_SIZE;
1127 for(int i = 0; i < NUMCORES; i++) {
1128 if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0)) {
1129 int memneed = gcrequiredmems[i] + BAMBOO_CACHE_LINE_SIZE;
1130 if(STARTUPCORE == i) {
1132 gcmovestartaddr = p;
1133 gcdstcore = gctopcore;
1134 gcblock2fill = numblocks + 1;
1136 send_msg_4(i, GCMOVESTART, gctopcore, p, numblocks + 1);
1138 if(memneed < remain) {
1140 gcrequiredmems[i] = 0;
1142 gcloads[gctopcore] += memneed;
1144 // next available block
1146 gcfilledblocks[gctopcore] += 1;
1148 BASEPTR(gctopcore, gcfilledblocks[gctopcore], &newbase);
1149 gcloads[gctopcore] = newbase;
1150 gcrequiredmems[i] -= remain - BAMBOO_CACHE_LINE_SIZE;
1151 gcstopblock[gctopcore]++;
1152 if(gcheapdirection) {
1154 if(gctopcore== NUMCORES) {
1156 gcheapdirection = false;
1162 gcheapdirection = true;
1165 numblocks = gcstopblock[gctopcore];
1166 BASEPTR(gctopcore, numblocks, &p);
1168 remain = b<NUMCORES ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1169 } // if(memneed < remain)
1170 } // if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0))
1171 } // for(i = 0; i < NUMCORES; i++)
1172 } // void compact2Heaptop()
1174 inline void resolvePendingMoveRequest() {
1176 BAMBOO_DEBUGPRINT(0xeb01);
1180 bool nosparemem = true;
1181 bool haspending = false;
1182 bool hasrunning = false;
1183 bool noblock = false;
1186 for(i = j = 0; (i < NUMCORES) && (j < NUMCORES);) {
1188 // check if there are cores with spare mem
1189 if(gccorestatus[i] == 0) {
1190 // finished working, check if it still have spare mem
1191 if(gcfilledblocks[i] < gcstopblock[i]) {
1192 // still have spare mem
1195 } // if(gcfilledblocks[i] < gcstopblock[i]) else ...
1200 if(gccorestatus[j] != 0) {
1201 // not finished, check if it has pending move requests
1202 if((gcfilledblocks[j]==gcstopblock[j])&&(gcrequiredmems[j]>0)) {
1207 } // if((gcfilledblocks[i] == gcstopblock[i])...) else ...
1208 } // if(gccorestatus[i] == 0) else ...
1210 } // if(!haspending)
1211 if(!nosparemem && haspending) {
1215 BAMBOO_START_CRITICAL_SECTION();
1216 gcrequiredmems[dstcore] = assignSpareMem_I(sourcecore,
1217 gcrequiredmems[dstcore],
1220 BAMBOO_CLOSE_CRITICAL_SECTION();
1221 if(STARTUPCORE == dstcore) {
1222 gcdstcore = sourcecore;
1224 gcmovestartaddr = startaddr;
1225 gcblock2fill = tomove;
1227 send_msg_4(dstcore, GCMOVESTART, sourcecore, startaddr, tomove);
1229 if(gcrequiredmems[dstcore] == 0) {
1236 } // for(i = 0; i < NUMCORES; i++)
1238 BAMBOO_DEBUGPRINT(0xcccc);
1239 BAMBOO_DEBUGPRINT_REG(hasrunning);
1240 BAMBOO_DEBUGPRINT_REG(haspending);
1241 BAMBOO_DEBUGPRINT_REG(noblock);
1244 if(!hasrunning && !noblock) {
1245 gcphase = SUBTLECOMPACTPHASE;
1249 } // void resovePendingMoveRequest()
1252 int numblocks; // block num for heap
1253 INTPTR base; // base virtual address of current heap block
1254 INTPTR ptr; // virtual address of current heap top
1255 int offset; // offset in current heap block
1256 int blockbase; // virtual address of current small block to check
1257 int blockbound; // bound virtual address of current small blcok
1258 int sblockindex; // index of the small blocks
1259 int top; // real size of current heap block to check
1260 int bound; // bound size of current heap block to check
1261 }; // struct moveHelper
1263 inline void nextSBlock(struct moveHelper * orig) {
1264 orig->blockbase = orig->blockbound;
1266 if(orig->blockbase >= orig->bound) {
1267 // end of current heap block, jump to next one
1269 BASEPTR(BAMBOO_NUM_OF_CORE, orig->numblocks, &(orig->base));
1270 orig->bound = orig->base + BAMBOO_SMEM_SIZE;
1271 orig->blockbase = orig->base;
1273 orig->sblockindex = (orig->blockbase-BAMBOO_BASE_VA)/BAMBOO_SMEM_SIZE;
1274 if(gcsbstarttbl[orig->sblockindex] == -1) {
1276 orig->sblockindex += 1;
1277 orig->blockbase += BAMBOO_SMEM_SIZE;
1278 goto innernextSBlock;
1279 } else if(gcsbstarttbl[orig->sblockindex] != 0) {
1280 // not start from the very beginning
1281 orig->blockbase = gcsbstarttbl[orig->sblockindex];
1283 orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1284 orig->offset = BAMBOO_CACHE_LINE_SIZE;
1285 orig->ptr = orig->blockbase + orig->offset;
1286 } // void nextSBlock(struct moveHelper * orig)
1288 inline void initOrig_Dst(struct moveHelper * orig,
1289 struct moveHelper * to) {
1292 to->top = to->offset = BAMBOO_CACHE_LINE_SIZE;
1293 to->bound = BAMBOO_SMEM_SIZE_L;
1294 BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1295 /*if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1296 to->base += gcreservedsb * BAMBOO_SMEM_SIZE;
1297 to->top += gcreservedsb * BAMBOO_SMEM_SIZE;
1299 to->ptr = to->base + to->offset;
1301 // init the orig ptr
1302 orig->numblocks = 0;
1303 orig->base = to->base;
1304 orig->bound = to->base + BAMBOO_SMEM_SIZE_L;
1305 orig->blockbase = orig->base;
1306 /*if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1307 orig->sblockindex = gcreservedsb;
1309 orig->sblockindex = (orig->base - BAMBOO_BASE_VA) / BAMBOO_SMEM_SIZE;
1311 if(gcsbstarttbl[orig->sblockindex] == -1) {
1314 BAMBOO_BASE_VA+BAMBOO_SMEM_SIZE*(orig->sblockindex+1);
1317 } else if(gcsbstarttbl[orig->sblockindex] != 0) {
1318 orig->blockbase = gcsbstarttbl[orig->sblockindex];
1320 orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1321 orig->offset = BAMBOO_CACHE_LINE_SIZE;
1322 orig->ptr = orig->blockbase + orig->offset;
1323 } // void initOrig_Dst(struct moveHelper * orig, struct moveHelper * to)
1325 inline void nextBlock(struct moveHelper * to) {
1326 to->top = to->bound + BAMBOO_CACHE_LINE_SIZE; // header!
1327 to->bound += BAMBOO_SMEM_SIZE;
1329 BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1330 to->offset = BAMBOO_CACHE_LINE_SIZE;
1331 to->ptr = to->base + to->offset;
1332 } // void nextBlock(struct moveHelper * to)
1334 // endaddr does not contain spaces for headers
1335 inline bool moveobj(struct moveHelper * orig,
1336 struct moveHelper * to,
1338 if(stopblock == 0) {
1343 BAMBOO_DEBUGPRINT(0xe201);
1344 BAMBOO_DEBUGPRINT_REG(orig->ptr);
1345 BAMBOO_DEBUGPRINT_REG(to->ptr);
1353 while((char)(*((int*)(orig->ptr))) == (char)(-2)) {
1354 orig->ptr = (int*)(orig->ptr) + 1;
1356 if((orig->ptr > orig->bound) || (orig->ptr == orig->blockbound)) {
1361 BAMBOO_DEBUGPRINT(0xe202);
1363 // check the obj's type, size and mark flag
1364 type = ((int *)(orig->ptr))[0];
1367 // end of this block, go to next one
1370 } else if(type < NUMCLASSES) {
1372 size = classsize[type];
1375 struct ArrayObject *ao=(struct ArrayObject *)(orig->ptr);
1376 int elementsize=classsize[type];
1377 int length=ao->___length___;
1378 size=sizeof(struct ArrayObject)+length*elementsize;
1380 mark = ((int *)(orig->ptr))[6];
1382 BAMBOO_DEBUGPRINT(0xe203);
1386 BAMBOO_DEBUGPRINT(0xe204);
1388 // marked obj, copy it to current heap top
1389 // check to see if remaining space is enough
1390 ALIGNSIZE(size, &isize);
1391 if(to->top + isize > to->bound) {
1392 // fill -1 indicating the end of this block
1393 if(to->top != to->bound) {
1394 *((int*)to->ptr) = -1;
1396 //memset(to->ptr+1, -2, to->bound - to->top - 1);
1397 // fill the header of this block and then go to next block
1398 to->offset += to->bound - to->top;
1399 memset(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
1400 (*((int*)(to->base))) = to->offset;
1402 if(stopblock == to->numblocks) {
1403 // already fulfilled the block
1407 } // if(stopblock == to->numblocks)
1408 } // if(to->top + isize > to->bound)
1409 // set the mark field to 2, indicating that this obj has been moved and need to be flushed
1410 ((int *)(orig->ptr))[6] = 2;
1411 if(to->ptr != orig->ptr) {
1412 memcpy(to->ptr, orig->ptr, size);
1413 // fill the remaining space with -2
1414 memset(to->ptr+size, -2, isize-size);
1416 // store mapping info
1417 BAMBOO_START_CRITICAL_SECTION();
1418 RuntimeHashadd_I(gcpointertbl, orig->ptr, to->ptr);
1419 BAMBOO_CLOSE_CRITICAL_SECTION();
1421 BAMBOO_DEBUGPRINT(0xcdcd);
1422 BAMBOO_DEBUGPRINT_REG(orig->ptr);
1423 BAMBOO_DEBUGPRINT_REG(to->ptr);
1425 gccurr_heaptop -= isize;
1427 to->offset += isize;
1431 BAMBOO_DEBUGPRINT(0xe205);
1436 BAMBOO_DEBUGPRINT_REG(isize);
1437 BAMBOO_DEBUGPRINT_REG(orig->ptr);
1439 if((orig->ptr > orig->bound) || (orig->ptr == orig->blockbound)) {
1441 BAMBOO_DEBUGPRINT(0xe206);
1446 BAMBOO_DEBUGPRINT_REG(orig->ptr);
1449 } //bool moveobj(struct moveHelper* orig,struct moveHelper* to,int* endaddr)
1451 // should be invoked with interrupt closed
1452 inline int assignSpareMem_I(int sourcecore,
1457 BLOCKINDEX(gcloads[sourcecore], &b);
1458 int boundptr = b<NUMCORES?(b+1)*BAMBOO_SMEM_SIZE_L
1459 :BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES+1)*BAMBOO_SMEM_SIZE;
1460 int remain = boundptr - gcloads[sourcecore];
1461 int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
1462 *startaddr = gcloads[sourcecore];
1463 *tomove = gcfilledblocks[sourcecore] + 1;
1464 if(memneed < remain) {
1465 gcloads[sourcecore] += memneed;
1468 // next available block
1469 gcfilledblocks[sourcecore] += 1;
1471 BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
1472 gcloads[sourcecore] = newbase;
1473 return requiredmem-remain;
1475 } // int assignSpareMem_I(int ,int * , int * , int * )
1477 // should be invoked with interrupt closed
1478 inline bool gcfindSpareMem_I(int * startaddr,
1483 for(int k = 0; k < NUMCORES; k++) {
1484 if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
1485 // check if this stopped core has enough mem
1486 assignSpareMem_I(k, requiredmem, tomove, startaddr);
1491 // if can not find spare mem right now, hold the request
1492 gcrequiredmems[requiredcore] = requiredmem;
1495 } //bool gcfindSpareMem_I(int* startaddr,int* tomove,int mem,int core)
1497 inline bool compacthelper(struct moveHelper * orig,
1498 struct moveHelper * to,
1501 bool * localcompact) {
1502 // scan over all objs in this block, compact the marked objs
1503 // loop stop when finishing either scanning all active objs or
1504 // fulfilled the gcstopblock
1506 BAMBOO_DEBUGPRINT(0xe101);
1507 BAMBOO_DEBUGPRINT_REG(gcblock2fill);
1511 bool stop = moveobj(orig, to, gcblock2fill);
1515 } while(orig->ptr < gcmarkedptrbound);
1516 // if no objs have been compact, do nothing,
1517 // otherwise, fill the header of this block
1518 if(to->offset > BAMBOO_CACHE_LINE_SIZE) {
1519 memset(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
1520 (*((int*)(to->base))) = to->offset;
1524 to->top -= BAMBOO_CACHE_LINE_SIZE;
1525 } // if(to->offset > BAMBOO_CACHE_LINE_SIZE) else ...
1527 *heaptopptr = to->ptr;
1528 *filledblocks = to->numblocks;
1531 BAMBOO_DEBUGPRINT(0xe102);
1532 BAMBOO_DEBUGPRINT_REG(orig->ptr);
1533 BAMBOO_DEBUGPRINT_REG(gcmarkedptrbound);
1534 BAMBOO_DEBUGPRINT_REG(*heaptopptr);
1535 BAMBOO_DEBUGPRINT_REG(*filledblocks);
1538 // send msgs to core coordinator indicating that the compact is finishing
1539 // send compact finish message to core coordinator
1540 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1541 gcfilledblocks[BAMBOO_NUM_OF_CORE] = *filledblocks;
1542 gcloads[BAMBOO_NUM_OF_CORE] = *heaptopptr;
1543 if(orig->ptr < gcmarkedptrbound) {
1546 BAMBOO_START_CRITICAL_SECTION();
1547 if(gcfindSpareMem_I(&gcmovestartaddr, &gcblock2fill, &gcdstcore,
1548 gccurr_heaptop, BAMBOO_NUM_OF_CORE)) {
1551 BAMBOO_CLOSE_CRITICAL_SECTION();
1554 BAMBOO_CLOSE_CRITICAL_SECTION();
1556 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1560 if(orig->ptr < gcmarkedptrbound) {
1563 send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
1564 *filledblocks, *heaptopptr, gccurr_heaptop);
1566 // finish compacting
1567 send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
1568 *filledblocks, *heaptopptr, 0);
1570 } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
1572 if(orig->ptr < gcmarkedptrbound) {
1573 // still have unpacked obj
1574 while(!gctomove) {};
1577 to->ptr = gcmovestartaddr;
1578 to->numblocks = gcblock2fill - 1;
1579 to->bound = (to->numblocks==0)?
1581 BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
1582 BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1583 to->offset = to->ptr - to->base;
1584 to->top = (to->numblocks==0)?
1585 (to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
1587 to->offset = BAMBOO_CACHE_LINE_SIZE;
1588 to->ptr += to->offset; // for header
1589 to->top += to->offset;
1590 if(gcdstcore == BAMBOO_NUM_OF_CORE) {
1591 *localcompact = true;
1593 *localcompact = false;
1598 } // void compacthelper()
1600 inline void compact() {
1601 if(COMPACTPHASE != gcphase) {
1602 BAMBOO_EXIT(0xb102);
1605 // initialize pointers for comapcting
1606 struct moveHelper * orig =
1607 (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1608 struct moveHelper * to =
1609 (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1611 initOrig_Dst(orig, to);
1613 int filledblocks = 0;
1614 INTPTR heaptopptr = 0;
1615 bool localcompact = true;
1616 compacthelper(orig, to, &filledblocks, &heaptopptr, &localcompact);
1622 inline void * flushObj(void * objptr) {
1624 BAMBOO_DEBUGPRINT(0xe401);
1626 void * dstptr = NULL;
1627 if(ISSHAREDOBJ(objptr)) {
1629 BAMBOO_DEBUGPRINT(0xe402);
1630 BAMBOO_DEBUGPRINT_REG(objptr);
1632 // a shared obj ptr, change to new address
1633 BAMBOO_START_CRITICAL_SECTION();
1634 RuntimeHashget(gcpointertbl, objptr, &dstptr);
1635 BAMBOO_CLOSE_CRITICAL_SECTION();
1637 BAMBOO_DEBUGPRINT_REG(dstptr);
1639 if(NULL == dstptr) {
1641 BAMBOO_DEBUGPRINT(0xe403);
1643 // send msg to host core for the mapping info
1644 gcobj2map = (int)objptr;
1647 send_msg_3(hostcore(objptr), GCMAPREQUEST, (int)objptr,
1648 BAMBOO_NUM_OF_CORE);
1649 while(!gcismapped) {}
1650 BAMBOO_START_CRITICAL_SECTION();
1651 RuntimeHashget(gcpointertbl, objptr, &dstptr);
1652 BAMBOO_CLOSE_CRITICAL_SECTION();
1654 BAMBOO_DEBUGPRINT_REG(dstptr);
1657 } // if(ISSHAREDOBJ(objptr))
1659 BAMBOO_DEBUGPRINT(0xe404);
1662 } // void flushObj(void * objptr, void ** tochange)
1664 inline void flushRuntimeObj(struct garbagelist * stackptr) {
1666 // flush current stack
1667 while(stackptr!=NULL) {
1668 for(i=0; i<stackptr->size; i++) {
1669 if(stackptr->array[i] != NULL) {
1670 stackptr->array[i] = flushObj(stackptr->array[i]);
1673 stackptr=stackptr->next;
1677 for(i=0; i<NUMCLASSES; i++) {
1678 struct parameterwrapper ** queues =
1679 objectqueues[BAMBOO_NUM_OF_CORE][i];
1680 int length = numqueues[BAMBOO_NUM_OF_CORE][i];
1681 for(j = 0; j < length; ++j) {
1682 struct parameterwrapper * parameter = queues[j];
1683 struct ObjectHash * set=parameter->objectset;
1684 struct ObjectNode * ptr=set->listhead;
1686 ptr->key = flushObj((void *)ptr->key);
1692 // flush current task descriptor
1693 if(currtpd != NULL) {
1694 for(i=0; i<currtpd->numParameters; i++) {
1695 currtpd->parameterArray[i] = flushObj(currtpd->parameterArray[i]);
1699 // flush active tasks
1700 struct genpointerlist * ptr=activetasks->list;
1702 struct taskparamdescriptor *tpd=ptr->src;
1704 for(i=0; i<tpd->numParameters; i++) {
1705 tpd->parameterArray[i] = flushObj(tpd->parameterArray[i]);
1710 // flush cached transferred obj
1711 struct QueueItem * tmpobjptr = getHead(&objqueue);
1712 while(tmpobjptr != NULL) {
1713 struct transObjInfo * objInfo =
1714 (struct transObjInfo *)(tmpobjptr->objectptr);
1715 objInfo->objptr = flushObj(objInfo->objptr);
1716 tmpobjptr = getNextQueueItem(tmpobjptr);
1719 // flush cached objs to be transferred
1720 struct QueueItem * item = getHead(totransobjqueue);
1721 while(item != NULL) {
1722 struct transObjInfo * totransobj =
1723 (struct transObjInfo *)(item->objectptr);
1724 totransobj->objptr = flushObj(totransobj->objptr);
1725 item = getNextQueueItem(item);
1726 } // while(item != NULL)
1727 } // void flushRuntimeObj(struct garbagelist * stackptr)
1729 inline void flush(struct garbagelist * stackptr) {
1730 flushRuntimeObj(stackptr);
1731 while(gc_moreItems()) {
1733 BAMBOO_DEBUGPRINT(0xe301);
1735 void * ptr = gc_dequeue();
1737 BAMBOO_DEBUGPRINT_REG(ptr);
1739 void * tptr = flushObj(ptr);
1741 BAMBOO_DEBUGPRINT(0xe302);
1742 BAMBOO_DEBUGPRINT_REG(ptr);
1743 BAMBOO_DEBUGPRINT_REG(tptr);
1748 if(((int *)(ptr))[6] == 2) {
1749 int type = ((int *)(ptr))[0];
1750 // scan all pointers in ptr
1751 unsigned INTPTR * pointer;
1752 pointer=pointerarray[type];
1754 BAMBOO_DEBUGPRINT(0xe303);
1755 BAMBOO_DEBUGPRINT_REG(pointer);
1758 /* Array of primitives */
1760 } else if (((INTPTR)pointer)==1) {
1762 BAMBOO_DEBUGPRINT(0xe304);
1764 /* Array of pointers */
1765 struct ArrayObject *ao=(struct ArrayObject *) ptr;
1766 int length=ao->___length___;
1768 for(j=0; j<length; j++) {
1770 BAMBOO_DEBUGPRINT(0xe305);
1773 ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
1775 BAMBOO_DEBUGPRINT_REG(objptr);
1777 ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] =
1782 BAMBOO_DEBUGPRINT(0xe306);
1784 INTPTR size=pointer[0];
1786 for(i=1; i<=size; i++) {
1788 BAMBOO_DEBUGPRINT(0xe307);
1790 unsigned int offset=pointer[i];
1791 void * objptr=*((void **)(((char *)ptr)+offset));
1793 BAMBOO_DEBUGPRINT_REG(objptr);
1795 *((void **)(((char *)ptr)+offset)) = flushObj(objptr);
1796 } // for(i=1; i<=size; i++)
1797 } // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
1798 // restore the mark field, indicating that this obj has been flushed
1799 ((int *)(ptr))[6] = 0;
1800 } // if(((int *)(ptr))[6] == 2)
1801 } // while(moi != NULL)
1803 BAMBOO_DEBUGPRINT(0xe308);
1805 // send flush finish message to core coordinator
1806 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1807 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1809 send_msg_2(STARTUPCORE, GCFINISHFLUSH, BAMBOO_NUM_OF_CORE);
1812 BAMBOO_DEBUGPRINT(0xe309);
1816 inline void gc_collect(struct garbagelist * stackptr) {
1817 // core collector routine
1819 tprintf("Do initGC\n");
1822 //send init finish msg to core coordinator
1823 send_msg_2(STARTUPCORE, GCFINISHINIT, BAMBOO_NUM_OF_CORE);
1825 tprintf("Start mark phase\n");
1827 mark(true, stackptr);
1829 tprintf("Finish mark phase, start compact phase\n");
1833 tprintf("Finish compact phase\n");
1835 while(FLUSHPHASE != gcphase) {}
1837 tprintf("Start flush phase\n");
1841 tprintf("Finish flush phase\n");
1844 while(FINISHPHASE != gcphase) {}
1846 tprintf("Finish gc!\n");
1848 } // void gc_collect(struct garbagelist * stackptr)
1850 inline void gc(struct garbagelist * stackptr) {
1856 // core coordinator routine
1857 if(0 == BAMBOO_NUM_OF_CORE) {
1859 tprintf("Check if can do gc or not\n");
1862 // not ready to do gc
1868 tprintf("start gc! \n");
1872 gcprocessing = true;
1874 waitconfirm = false;
1876 gcphase = MARKPHASE;
1877 for(i = 1; i < NUMCORES; i++) {
1878 // send GC init messages to all cores
1879 send_msg_1(i, GCSTARTINIT);
1881 bool isfirst = true;
1882 bool allStall = false;
1886 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1887 while(!gc_checkCoreStatus()) {}
1888 // all cores have finished compacting
1889 // restore the gcstatus of all cores
1890 gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
1891 for(i = 1; i < NUMCORES; ++i) {
1892 gccorestatus[i] = 1;
1893 // send GC start messages to all cores
1894 send_msg_1(i, GCSTART);
1898 while(MARKPHASE == gcphase) {
1899 mark(isfirst, stackptr);
1906 } // while(MARKPHASE == gcphase)
1907 // send msgs to all cores requiring large objs info
1908 numconfirm = NUMCORES - 1;
1909 for(i = 1; i < NUMCORES; ++i) {
1910 send_msg_1(i, GCLOBJREQUEST);
1912 gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
1913 while(numconfirm != 0) {} // wait for responses
1915 tprintf("prepare to cache large objs \n");
1918 // cache all large objs
1920 // no enough space to cache large objs
1921 BAMBOO_EXIT(0xb103);
1923 // predict number of blocks to fill for each core
1924 int numpbc = loadbalance();
1925 for(i = 0; i < NUMCORES; ++i) {
1926 //send start compact messages to all cores
1927 if((gcheapdirection) && (i < gctopcore)
1928 || ((!gcheapdirection) && (i > gctopcore))) {
1929 gcstopblock[i] =numpbc + 1;
1930 if(i != STARTUPCORE) {
1931 send_msg_2(i, GCSTARTCOMPACT, numpbc+1);
1933 gcblock2fill = numpbc+1;
1934 } // if(i != STARTUPCORE)
1936 gcstopblock[i] = numpbc;
1937 if(i != STARTUPCORE) {
1938 send_msg_2(i, GCSTARTCOMPACT, numpbc);
1940 gcblock2fill = numpbc;
1941 } // if(i != STARTUPCORE)
1943 // init some data strutures for compact phase
1945 gcfilledblocks[i] = 0;
1946 gcrequiredmems[i] = 0;
1949 tprintf("mark phase finished \n");
1954 bool finalcompact = false;
1955 // initialize pointers for comapcting
1956 struct moveHelper * orig =
1957 (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1958 struct moveHelper * to =
1959 (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1960 initOrig_Dst(orig, to);
1961 int filledblocks = 0;
1962 INTPTR heaptopptr = 0;
1963 bool finishcompact = false;
1964 bool iscontinue = true;
1965 bool localcompact = true;
1966 while((COMPACTPHASE == gcphase) || (SUBTLECOMPACTPHASE == gcphase)) {
1967 if((!finishcompact) && iscontinue) {
1969 BAMBOO_DEBUGPRINT(0xe001);
1970 BAMBOO_DEBUGPRINT_REG(gcblock2fill);
1972 finishcompact = compacthelper(orig, to, &filledblocks,
1973 &heaptopptr, &localcompact);
1975 BAMBOO_DEBUGPRINT_REG(finishcompact);
1976 BAMBOO_DEBUGPRINT_REG(gctomove);
1977 BAMBOO_DEBUGPRINT_REG(gcrequiredmems[0]);
1978 BAMBOO_DEBUGPRINT_REG(gcfilledblocks[0]);
1979 BAMBOO_DEBUGPRINT_REG(gcstopblock[0]);
1984 if(gc_checkCoreStatus()) {
1985 // all cores have finished compacting
1986 // restore the gcstatus of all cores
1987 for(i = 0; i < NUMCORES; ++i) {
1988 gccorestatus[i] = 1;
1992 // check if there are spare mem for pending move requires
1993 if(COMPACTPHASE == gcphase) {
1994 resolvePendingMoveRequest();
1997 BAMBOO_DEBUGPRINT(0xe002);
2001 } // if(gc_checkCoreStatus()) else ...
2005 BAMBOO_DEBUGPRINT(0xe003);
2006 BAMBOO_DEBUGPRINT_REG(gcmovestartaddr);
2007 BAMBOO_DEBUGPRINT_REG(gcblock2fill);
2008 BAMBOO_DEBUGPRINT_REG(gctomove);
2010 to->ptr = gcmovestartaddr;
2011 to->numblocks = gcblock2fill - 1;
2012 to->bound = (to->numblocks==0)?
2014 BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
2015 BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
2016 to->offset = to->ptr - to->base;
2017 to->top = (to->numblocks==0)?
2018 (to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
2020 to->offset = BAMBOO_CACHE_LINE_SIZE;
2021 to->ptr += to->offset; // for header
2022 to->top += to->offset;
2023 if(gcdstcore == BAMBOO_NUM_OF_CORE) {
2024 localcompact = true;
2026 localcompact = false;
2030 } else if(!finishcompact) {
2035 } // while(COMPACTPHASE == gcphase)
2037 tprintf("prepare to move large objs \n");
2043 tprintf("compact phase finished \n");
2047 gcphase = FLUSHPHASE;
2048 for(i = 1; i < NUMCORES; ++i) {
2049 // send start flush messages to all cores
2050 send_msg_1(i, GCSTARTFLUSH);
2055 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
2056 while(FLUSHPHASE == gcphase) {
2057 // check the status of all cores
2059 for(i = 0; i < NUMCORES; ++i) {
2060 if(gccorestatus[i] != 0) {
2068 } // while(FLUSHPHASE == gcphase)
2069 gcphase = FINISHPHASE;
2070 for(i = 1; i < NUMCORES; ++i) {
2071 // send gc finish messages to all cores
2072 send_msg_1(i, GCFINISH);
2075 tprintf("flush phase finished \n");
2079 // need to create free memory list
2080 updateFreeMemList();
2082 tprintf("gc finished \n");
2086 gcprocessing = true;
2087 gc_collect(stackptr);
2090 // invalidate all shared mem pointers
2091 bamboo_cur_msp = NULL;
2092 bamboo_smem_size = 0;
2095 gcprocessing = false;
2097 } // void gc(struct garbagelist * stackptr)