894ef49fdc4619311766c20aea6253cb6b521c87
[IRC.git] / Robust / src / Runtime / multicoregarbage.c
1 #ifdef MULTICORE_GC
2 #include "runtime.h"
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"
9
10 extern int corenum;
11 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
12 extern int numqueues[][NUMCLASSES];
13
14 extern struct genhashtable * activetasks;
15 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
16 extern struct taskparamdescriptor *currtpd;
17
18 struct pointerblock {
19   void * ptrs[NUMPTRS];
20   struct pointerblock *next;
21 };
22
23 struct pointerblock *gchead=NULL;
24 int gcheadindex=0;
25 struct pointerblock *gctail=NULL;
26 int gctailindex=0;
27 struct pointerblock *gctail2=NULL;
28 int gctailindex2=0;
29 struct pointerblock *gcspare=NULL;
30
31 #define NUMLOBJPTRS 20
32
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;
40 };
41
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;
49
50 #ifdef GC_DEBUG
51 inline void dumpSMem() {
52         tprintf("Dump shared mem: \n");
53         for (int i = BAMBOO_BASE_VA; i < BAMBOO_BASE_VA+BAMBOO_SHARED_MEM_SIZE; i += 4*16)
54     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",
55             *((int *)(i)), *((int *)(i + 4)), *((int *)(i + 4*2)), *((int *)(i + 4*3)), 
56                                                 *((int *)(i + 4*4)), *((int *)(i + 4*5)), *((int *)(i + 4*6)), *((int *)(i + 4*7)), 
57                                                 *((int *)(i + 4*8)), *((int *)(i + 4*9)), *((int *)(i + 4*10)), *((int *)(i + 4*11)),
58                                                 *((int *)(i + 4*12)), *((int *)(i + 4*13)), *((int *)(i + 4*14)), *((int *)(i + 4*15)));
59         tprintf("\n");
60 }
61 #endif
62
63 inline void gc_enqueue(void *ptr) {
64 #ifdef GC_DEBUG
65         BAMBOO_DEBUGPRINT(0xe601);
66         BAMBOO_DEBUGPRINT_REG(ptr);
67 #endif
68   if (gcheadindex==NUMPTRS) {
69     struct pointerblock * tmp;
70     if (gcspare!=NULL) {
71       tmp=gcspare;
72       gcspare=NULL;
73     } else {
74       tmp=RUNMALLOC(sizeof(struct pointerblock));
75                 } // if (gcspare!=NULL)
76     gchead->next=tmp;
77     gchead=tmp;
78     gcheadindex=0;
79   } // if (gcheadindex==NUMPTRS)
80   gchead->ptrs[gcheadindex++]=ptr;
81 } // void gc_enqueue(void *ptr)
82
83 // dequeue and destroy the queue
84 inline void * gc_dequeue() {
85   if (gctailindex==NUMPTRS) {
86     struct pointerblock *tmp=gctail;
87     gctail=gctail->next;
88     gctailindex=0;
89     if (gcspare!=NULL) {
90       RUNFREE(tmp);
91                 } else {
92       gcspare=tmp;
93                 } // if (gcspare!=NULL)
94   } // if (gctailindex==NUMPTRS)
95   return gctail->ptrs[gctailindex++];
96 } // void * gc_dequeue()
97
98 // dequeue and do not destroy the queue
99 inline void * gc_dequeue2() {
100         if (gctailindex2==NUMPTRS) {
101     struct pointerblock *tmp=gctail2;
102     gctail2=gctail2->next;
103     gctailindex2=0;
104   } // if (gctailindex2==NUMPTRS)
105   return gctail2->ptrs[gctailindex2++];
106 } // void * gc_dequeue2() 
107
108 inline int gc_moreItems() {
109   if ((gchead==gctail)&&(gctailindex==gcheadindex))
110     return 0;
111   return 1;
112 } // int gc_moreItems() 
113
114 inline int gc_moreItems2() {
115   if ((gchead==gctail2)&&(gctailindex2==gcheadindex))
116     return 0;
117   return 1;
118 } // int gc_moreItems2()
119
120 // enqueue a large obj: start addr & length
121 inline void gc_lobjenqueue(void *ptr, 
122                                        int length, 
123                                                                                        int host) {
124 #ifdef GC_DEBUG
125         BAMBOO_DEBUGPRINT(0xe901);
126 #endif
127   if (gclobjheadindex==NUMLOBJPTRS) {
128     struct lobjpointerblock * tmp;
129     if (gclobjspare!=NULL) {
130       tmp=gclobjspare;
131       gclobjspare=NULL;
132     } else {
133       tmp=RUNMALLOC(sizeof(struct lobjpointerblock));
134                 } // if (gclobjspare!=NULL)
135     gclobjhead->next=tmp;
136     gclobjhead=tmp;
137     gclobjheadindex=0;
138   } // if (gclobjheadindex==NUMLOBJPTRS)
139   gclobjhead->lobjs[gclobjheadindex]=ptr;
140         gclobjhead->lengths[gclobjheadindex]=length;
141         gclobjhead->hosts[gclobjheadindex++]=host;
142 #ifdef GC_DEBUG
143         BAMBOO_DEBUGPRINT_REG(gclobjhead->lobjs[gclobjheadindex-1]);
144         BAMBOO_DEBUGPRINT_REG(gclobjhead->lengths[gclobjheadindex-1]);
145         BAMBOO_DEBUGPRINT_REG(gclobjhead->hosts[gclobjheadindex-1]);
146 #endif
147 } // void gc_lobjenqueue(void *ptr...)
148
149 // dequeue and destroy the queue
150 inline void * gc_lobjdequeue(int * length,
151                                          int * host) {
152   if (gclobjtailindex==NUMLOBJPTRS) {
153     struct lobjpointerblock *tmp=gclobjtail;
154     gclobjtail=gclobjtail->next;
155     gclobjtailindex=0;
156     if (gclobjspare!=NULL) {
157       RUNFREE(tmp);
158                 } else {
159       gclobjspare=tmp;
160                 } // if (gclobjspare!=NULL)
161   } // if (gclobjtailindex==NUMLOBJPTRS)
162         if(length != NULL) {
163                 *length = gclobjtail->lengths[gclobjtailindex];
164         }
165         if(host != NULL) {
166                 *host = (int)(gclobjtail->hosts[gclobjtailindex]);
167         }
168   return gclobjtail->lobjs[gclobjtailindex++];
169 } // void * gc_lobjdequeue()
170
171 inline int gc_lobjmoreItems() {
172   if ((gclobjhead==gclobjtail)&&(gclobjtailindex==gclobjheadindex))
173     return 0;
174   return 1;
175 } // int gc_lobjmoreItems()
176
177 // dequeue and don't destroy the queue
178 inline void gc_lobjdequeue2() {
179   if (gclobjtailindex2==NUMLOBJPTRS) {
180     gclobjtail2=gclobjtail2->next;
181     gclobjtailindex2=1;
182   } else {
183                 gclobjtailindex2++;
184         }// if (gclobjtailindex2==NUMLOBJPTRS)
185 } // void * gc_lobjdequeue2()
186
187 inline int gc_lobjmoreItems2() {
188   if ((gclobjhead==gclobjtail2)&&(gclobjtailindex2==gclobjheadindex))
189     return 0;
190   return 1;
191 } // int gc_lobjmoreItems2()
192
193 INTPTR gccurr_heapbound = 0;
194
195 inline void gettype_size(void * ptr, 
196                                      int * ttype, 
197                                                                          int * tsize) {
198         int type = ((int *)ptr)[0];
199         int size = 0;
200         if(type < NUMCLASSES) {
201                 // a normal object
202                 size = classsize[type];
203         } else {        
204                 // an array 
205                 struct ArrayObject *ao=(struct ArrayObject *)ptr;
206                 int elementsize=classsize[type];
207                 int length=ao->___length___; 
208                 size=sizeof(struct ArrayObject)+length*elementsize;
209         } // if(type < NUMCLASSES)
210         *ttype = type;
211         *tsize = size;
212 }
213
214 inline bool isLarge(void * ptr, 
215                                 int * ttype, 
216                                                                                 int * tsize) {
217 #ifdef GC_DEBUG
218                 BAMBOO_DEBUGPRINT(0xe701);
219                 BAMBOO_DEBUGPRINT_REG(ptr);
220 #endif
221         // check if a pointer is referring to a large object
222         gettype_size(ptr, ttype, tsize);
223 #ifdef GC_DEBUG
224         BAMBOO_DEBUGPRINT(*tsize);
225 #endif
226         int bound = (BAMBOO_SMEM_SIZE);
227         if((int)(ptr-(BAMBOO_BASE_VA)) < (BAMBOO_LARGE_SMEM_BOUND)) {
228                 bound = (BAMBOO_SMEM_SIZE_L);
229         }
230         if((((int)(ptr-(BAMBOO_BASE_VA)))%(bound))==0) {
231                 // ptr is a start of a block
232 #ifdef GC_DEBUG
233                 BAMBOO_DEBUGPRINT(0xe702);
234                 BAMBOO_DEBUGPRINT(1);
235 #endif
236                 return true;
237         }
238         if((bound-(((int)(ptr-(BAMBOO_BASE_VA)))%bound)) < (*tsize)) {
239                 // it acrosses the boundary of current block
240 #ifdef GC_DEBUG
241                 BAMBOO_DEBUGPRINT(0xe703);
242                 BAMBOO_DEBUGPRINT(1);
243 #endif
244                 return true;
245         }
246 #ifdef GC_DEBUG
247                 BAMBOO_DEBUGPRINT(0);
248 #endif
249         return false;
250 } // bool isLarge(void * ptr, int * ttype, int * tsize)
251
252 inline int hostcore(void * ptr) {
253         // check the host core of ptr
254         int host = 0;
255         int x = 0;
256         int y = 0;
257         RESIDECORE(ptr, &x, &y);
258         host = (x==0)?(x*bamboo_height+y):(x*bamboo_height+y-2);
259         return host;
260 } // int hostcore(void * ptr)
261
262 inline bool isLocal(void * ptr) {
263         // check if a pointer is in shared heap on this core
264         return hostcore(ptr) == BAMBOO_NUM_OF_CORE;
265 } // bool isLocal(void * ptr)
266
267 inline bool gc_checkCoreStatus() {
268         bool allStall = true;
269         for(int i = 0; i < NUMCORES; ++i) {
270                 if(gccorestatus[i] != 0) {
271                         allStall = false;
272                         break;
273                 } // if(gccorestatus[i] != 0)
274         } // for(i = 0; i < NUMCORES; ++i)
275         return allStall;
276 }
277
278 inline void checkMarkStatue() {
279         int i;
280         if((!waitconfirm) || 
281                         (waitconfirm && (numconfirm == 0))) {
282                 BAMBOO_START_CRITICAL_SECTION_STATUS();  
283                 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
284                 gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
285                 gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
286                 // check the status of all cores
287                 bool allStall = gc_checkCoreStatus();
288                 if(allStall) {
289                         // check if the sum of send objs and receive obj are the same
290                         // yes->check if the info is the latest; no->go on executing
291                         int sumsendobj = 0;
292                         for(i = 0; i < NUMCORES; ++i) {
293                                 sumsendobj += gcnumsendobjs[i];
294                         } // for(i = 0; i < NUMCORES; ++i) 
295                         for(i = 0; i < NUMCORES; ++i) {
296                                 sumsendobj -= gcnumreceiveobjs[i];
297                         } // for(i = 0; i < NUMCORES; ++i) 
298                         if(0 == sumsendobj) {
299                                 if(!waitconfirm) {
300                                         // the first time found all cores stall
301                                         // send out status confirm msg to all other cores
302                                         // reset the corestatus array too
303                                         gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
304                                         waitconfirm = true;
305                                         numconfirm = NUMCORES - 1;
306                                         for(i = 1; i < NUMCORES; ++i) { 
307                                                 gccorestatus[i] = 1;
308                                                 // send mark phase finish confirm request msg to core i
309                                                 send_msg_1(i, GCMARKCONFIRM);
310                                         } // for(i = 1; i < NUMCORES; ++i) 
311                                 } else {
312                                         // all the core status info are the latest
313                                         // stop mark phase
314                                         gcphase = COMPACTPHASE;
315                                         // restore the gcstatus for all cores
316                                         for(i = 0; i < NUMCORES; ++i) {
317                                                 gccorestatus[i] = 1;
318                                         } // for(i = 0; i < NUMCORES; ++i)
319                                 } // if(!gcwautconfirm) else()
320                         } // if(0 == sumsendobj)
321                 } // if(allStall)
322                 BAMBOO_CLOSE_CRITICAL_SECTION_STATUS();
323         } // if((!waitconfirm)...
324 } // void checkMarkStatue()
325
326 inline bool preGC() {
327         // preparation for gc
328         // make sure to clear all incoming msgs espacially transfer obj msgs
329         int i;
330         if((!waitconfirm) || 
331                                                   (waitconfirm && (numconfirm == 0))) {
332                 // send out status confirm msgs to all cores to check if there are
333                 // transfer obj msgs on-the-fly
334                 waitconfirm = true;
335                 numconfirm = NUMCORES - 1;
336                 for(i = 1; i < NUMCORES; ++i) { 
337                         corestatus[i] = 1;
338                         // send status confirm msg to core i
339                         send_msg_1(i, STATUSCONFIRM);
340                 } // for(i = 1; i < NUMCORES; ++i)
341
342                 while(numconfirm != 0) {} // wait for confirmations
343                 numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
344                 numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
345                 int sumsendobj = 0;
346                 for(i = 0; i < NUMCORES; ++i) {
347                         sumsendobj += numsendobjs[i];
348                 } // for(i = 1; i < NUMCORES; ++i)      
349                 for(i = 0; i < NUMCORES; ++i) {
350                         sumsendobj -= numreceiveobjs[i];
351                 } // for(i = 1; i < NUMCORES; ++i)
352                 if(0 == sumsendobj) {
353                         return true;
354                 } else {
355                         // still have some transfer obj msgs on-the-fly, can not start gc
356                         return false;
357                 } // if(0 == sumsendobj) 
358         } else {
359                 // previously asked for status confirmation and do not have all the 
360                 // confirmations yet, can not start gc
361                 return false;
362         } // if((!waitconfirm) || 
363 } // bool preGC()
364
365 inline void initGC() {
366         int i;
367         for(i = 0; i < NUMCORES; ++i) {
368                 gccorestatus[i] = 1;
369                 gcnumsendobjs[i] = 0; 
370                 gcnumreceiveobjs[i] = 0;
371                 gcloads[i] = 0;
372                 gcrequiredmems[i] = 0;
373                 gcfilledblocks[i] = 0;
374                 gcstopblock[i] = 0;
375         } // for(i = 0; i < NUMCORES; ++i)
376         gcself_numsendobjs = 0;
377         gcself_numreceiveobjs = 0;
378         gcmarkedptrbound = 0;
379         gcobj2map = 0;
380         gcmappedobj = 0;
381         gcismapped = false;
382         gcnumlobjs = 0;
383         gcheaptop = 0;
384         gctopcore = 0;
385         gcheapdirection = 1;
386         gcmovestartaddr = 0;
387         gctomove = false;
388         gcblock2fill = 0;
389         gcmovepending = 0;
390
391         // initialize queue
392         if (gchead==NULL) {
393                 gcheadindex=gctailindex=gctailindex2 = 0;
394                 gchead=gctail=gctail2=RUNMALLOC(sizeof(struct pointerblock));
395         } else {
396                 gctailindex = gctailindex2 = gcheadindex;
397                 gctail = gctail2 = gchead;
398         }
399
400         // initialize the large obj queues
401         if (gclobjhead==NULL) {
402                 gclobjheadindex=0;
403                 gclobjtailindex=0;
404                 gclobjtailindex2 = 0;
405                 gclobjhead=gclobjtail=gclobjtail2=
406                         RUNMALLOC(sizeof(struct lobjpointerblock));
407         } else {
408                 gclobjtailindex = gclobjtailindex2 = gclobjheadindex;
409                 gclobjtail = gclobjtail2 = gclobjhead;
410         }
411 } // void initGC()
412
413 // compute load balance for all cores
414 inline int loadbalance() {
415         // compute load balance
416         int i;
417
418         // get the total loads
419         gcloads[BAMBOO_NUM_OF_CORE]+=
420                 BAMBOO_SMEM_SIZE*gcreservedsb;//reserved sblocks for sbstartbl
421         int tloads = gcloads[STARTUPCORE];
422         for(i = 1; i < NUMCORES; i++) {
423                 tloads += gcloads[i];
424         }
425         int heaptop = BAMBOO_BASE_VA + tloads;
426 #ifdef GC_DEBUG
427         BAMBOO_DEBUGPRINT(0xdddd);
428         BAMBOO_DEBUGPRINT_REG(tloads);
429         BAMBOO_DEBUGPRINT_REG(heaptop);
430 #endif
431         int b = 0;
432         BLOCKINDEX(heaptop, &b);
433         int numbpc = b / NUMCORES; // num of blocks per core
434 #ifdef GC_DEBUG
435         BAMBOO_DEBUGPRINT_REG(b);
436         BAMBOO_DEBUGPRINT_REG(numbpc);
437 #endif
438         gcheapdirection = (numbpc%2 == 0);
439         int x = 0;
440         int y = 0;
441         RESIDECORE(heaptop, &x, &y);
442         gctopcore = (x == 0 ? y : x * bamboo_height + y - 2);
443 #ifdef GC_DEBUG
444         BAMBOO_DEBUGPRINT_REG(gctopcore);
445 #endif
446         return numbpc;
447 } // void loadbalance()
448
449 inline bool cacheLObjs() {
450         // check the total mem size need for large objs
451         int sumsize = 0;
452         int size = 0;
453 #ifdef GC_DEBUG
454         BAMBOO_DEBUGPRINT(0xe801);
455 #endif
456         gclobjtail2 = gclobjtail;
457         gclobjtailindex2 = gclobjtailindex;
458         while(gc_lobjmoreItems2()){
459                 gc_lobjdequeue2();
460                 size = gclobjtail2->lengths[gclobjtailindex2 - 1];
461                 sumsize += size;
462 #ifdef GC_DEBUG
463                 BAMBOO_DEBUGPRINT_REG(size);
464                 BAMBOO_DEBUGPRINT_REG(sumsize);
465 #endif
466         } // while(gc_lobjmoreItems2())
467
468         // check if there are enough space to cache these large objs
469         INTPTR dst = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE) - sumsize;
470         if(gcheaptop > dst) {
471                 // do not have enough room to cache large objs
472                 return false;
473         }
474 #ifdef GC_DEBUG
475         BAMBOO_DEBUGPRINT(0xe802);
476         BAMBOO_DEBUGPRINT_REG(dst);
477 #endif
478
479         gcheaptop = dst; // Note: record the start of cached lobjs with gcheaptop
480         // cache the largeObjs to the top of the shared heap
481         gclobjtail2 = gclobjtail;
482         gclobjtailindex2 = gclobjtailindex;
483         while(gc_lobjmoreItems2()) {
484                 gc_lobjdequeue2();
485                 size = gclobjtail2->lengths[gclobjtailindex2 - 1];
486                 memcpy(dst, gclobjtail2->lobjs[gclobjtailindex2 - 1], size);
487                 dst += size;
488 #ifdef GC_DEBUG
489                 BAMBOO_DEBUGPRINT_REG(gclobjtail2->lobjs[gclobjtailindex2-1]);
490                 BAMBOO_DEBUGPRINT(dst-size);
491                 BAMBOO_DEBUGPRINT_REG(size);
492 #endif
493         }
494         return true;
495 } // void cacheLObjs()
496
497 inline void moveLObjs() {
498 #ifdef GC_DEBUG
499         BAMBOO_DEBUGPRINT(0xea01);
500 #endif
501         // find current heap top
502         // flush all gcloads to indicate the real heap top on one core
503         // previous it represents the next available ptr on a core
504         if((gcloads[0] > ((BAMBOO_BASE_VA)+(BAMBOO_SMEM_SIZE_L))) 
505                         && ((gcloads[0] % (BAMBOO_SMEM_SIZE)) == 0)) {
506                 // edge of a block, check if this is exactly the heaptop
507                 BASEPTR(0, gcfilledblocks[0]-1, &(gcloads[0]));
508                 gcloads[0]+=(gcfilledblocks[0]>1?(BAMBOO_SMEM_SIZE):(BAMBOO_SMEM_SIZE_L));
509         }
510         int tmpheaptop = gcloads[0];
511 #ifdef GC_DEBUG
512         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
513 #endif
514         for(int i = 1; i < NUMCORES; i++) {
515                 if((gcloads[i] > ((BAMBOO_BASE_VA)+(BAMBOO_SMEM_SIZE_L))) 
516                                 && ((gcloads[i] % (BAMBOO_SMEM_SIZE)) == 0)) {
517                         // edge of a block, check if this is exactly the heaptop
518                         BASEPTR(0, gcfilledblocks[i]-1, &gcloads[i]);
519                         gcloads[i]+=(gcfilledblocks[i]>1?(BAMBOO_SMEM_SIZE):(BAMBOO_SMEM_SIZE_L));
520                 }
521                 if(tmpheaptop < gcloads[i]) {
522                         tmpheaptop = gcloads[i];
523                 }
524 #ifdef GC_DEBUG
525                 BAMBOO_DEBUGPRINT_REG(gcloads[i]);
526                 BAMBOO_DEBUGPRINT_REG(tmpheaptop);
527 #endif
528         }
529         // move large objs from gcheaptop to tmpheaptop
530         // write the header first
531         int tomove = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE) - gcheaptop;
532 #ifdef GC_DEBUG
533         BAMBOO_DEBUGPRINT(0xea02);
534         BAMBOO_DEBUGPRINT_REG(tomove);
535 #endif
536         if(tomove == 0) {
537                 gcheaptop = tmpheaptop;
538                 return;
539         }
540         // check how many blocks it acrosses
541         int remain = tmpheaptop-(int)(BAMBOO_BASE_VA);
542         int b = remain/(BAMBOO_SMEM_SIZE);
543         // check the remaining space in this block
544         int bound = (BAMBOO_SMEM_SIZE);
545         if(remain < (BAMBOO_LARGE_SMEM_BOUND)) {
546                 bound = (BAMBOO_SMEM_SIZE_L);
547         }
548         remain = bound - remain%bound;
549         // flush the sbstartbl
550         memset(&(gcsbstarttbl[gcreservedsb]), '\0', 
551                            BAMBOO_SHARED_MEM_SIZE/BAMBOO_SMEM_SIZE*sizeof(INTPTR));
552
553 #ifdef GC_DEBUG
554         BAMBOO_DEBUGPRINT(0xea03);
555 #endif
556         int size = 0;
557         int isize = 0;
558         int host = 0;
559         int ptr = 0;
560         int base = tmpheaptop;
561         int cpysize = 0;
562         remain -= BAMBOO_CACHE_LINE_SIZE;
563         tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
564         while(gc_lobjmoreItems()) {
565                 ptr = (int)(gc_lobjdequeue(&size, &host));
566                 ALIGNSIZE(size, &isize);
567                 if(remain < isize) {
568                         // this object acrosses blocks
569                         if(cpysize > 0) {
570                                 // close current block, fill its header
571                                 *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
572                                 cpysize = 0;
573                                 base = tmpheaptop;
574                                 if(remain == 0) {
575                                         remain = ((tmpheaptop-(BAMBOO_BASE_VA))<(BAMBOO_LARGE_SMEM_BOUND)) ? 
576                                                        BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
577                                 } 
578                                 remain -= BAMBOO_CACHE_LINE_SIZE;
579                                 tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
580                         } // if(cpysize > 0)
581
582                         // move the large obj
583                         memcpy(tmpheaptop, gcheaptop, size);
584                         // fill the remaining space with -2 padding
585                         memset(tmpheaptop+size, -2, isize-size);
586 #ifdef GC_DEBUG
587                         BAMBOO_DEBUGPRINT(0xea04);
588                         BAMBOO_DEBUGPRINT_REG(gcheaptop);
589                         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
590                         BAMBOO_DEBUGPRINT_REG(size);
591                         BAMBOO_DEBUGPRINT_REG(isize);
592 #endif
593                         gcheaptop += size;
594                         if(host == BAMBOO_NUM_OF_CORE) {
595                                 BAMBOO_START_CRITICAL_SECTION();
596                                 RuntimeHashadd(gcpointertbl, ptr, tmpheaptop);
597                                 BAMBOO_CLOSE_CRITICAL_SECTION();
598                         } else {
599                                 // send the original host core with the mapping info
600                                 send_msg_3(host, GCLOBJMAPPING, ptr, tmpheaptop);
601                         } // if(host == BAMBOO_NUM_OF_CORE) else ...
602                         tmpheaptop += isize;
603
604                         // set the gcsbstarttbl
605                         int tmpsbs = 1+(isize-remain-1)/BAMBOO_SMEM_SIZE;
606                         for(int k = 1; k < tmpsbs; k++) {
607                                 gcsbstarttbl[b+k] = (INTPTR)(-1);
608                         }
609                         b += tmpsbs;
610                         if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) {
611                                 gcsbstarttbl[b] = (INTPTR)(-1);
612                                 remain = ((tmpheaptop-(BAMBOO_BASE_VA))<(BAMBOO_LARGE_SMEM_BOUND)) ? 
613                                                      BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
614                         } else {
615                                 gcsbstarttbl[b] = (INTPTR)(tmpheaptop);
616                                 remain = tmpheaptop-(BAMBOO_BASE_VA);
617                                 int bound = remain<(BAMBOO_LARGE_SMEM_BOUND)?(BAMBOO_SMEM_SIZE_L):(BAMBOO_SMEM_SIZE);
618                                 remain = bound - remain%bound;
619                         } // if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) else ...
620
621                         // close current block and fill the header
622                         *((int*)base) = isize + BAMBOO_CACHE_LINE_SIZE;
623                         cpysize = 0;
624                         base = tmpheaptop;
625                         remain -= BAMBOO_CACHE_LINE_SIZE;
626                         tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
627                 } else {
628                         remain -= isize;
629                         // move the large obj
630                         memcpy(tmpheaptop, gcheaptop, size);
631                         // fill the remaining space with -2 padding
632                         memset(tmpheaptop+size, -2, isize-size);
633 #ifdef GC_DEBUG
634                         BAMBOO_DEBUGPRINT(0xea05);
635                         BAMBOO_DEBUGPRINT_REG(gcheaptop);
636                         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
637                         BAMBOO_DEBUGPRINT_REG(size);
638                         BAMBOO_DEBUGPRINT_REG(isize);
639 #endif
640                         gcheaptop += size;
641                         cpysize += isize;
642                         if(host == BAMBOO_NUM_OF_CORE) {
643                                 BAMBOO_START_CRITICAL_SECTION();
644                                 RuntimeHashadd(gcpointertbl, ptr, tmpheaptop);
645                                 BAMBOO_CLOSE_CRITICAL_SECTION();
646                         } else {
647                                 // send the original host core with the mapping info
648                                 send_msg_3(host, GCLOBJMAPPING, ptr, tmpheaptop);
649                         } // if(host == BAMBOO_NUM_OF_CORE) else ...
650                         tmpheaptop += isize;
651                 } // if(remain < isize) else ...
652         } // while(gc_lobjmoreItems())
653         if(cpysize > 0) {
654                 // close current block, fill the head
655                 *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
656         } else {
657                 tmpheaptop -= BAMBOO_CACHE_LINE_SIZE;
658         }
659         gcheaptop = tmpheaptop;
660 #ifdef GC_DEBUG
661         BAMBOO_DEBUGPRINT(0xea06);
662         BAMBOO_DEBUGPRINT_REG(gcheaptop);
663 #endif
664 } // void moveLObjs()
665
666 inline void updateFreeMemList() {
667         struct freeMemItem * tochange = bamboo_free_mem_list->head;
668         if(tochange == NULL) {
669                 bamboo_free_mem_list->head = tochange = 
670                         (struct freeMemItem *)RUNMALLOC(sizeof(struct freeMemItem));
671         }
672         // handle the top of the heap
673         tochange->ptr = gcheaptop;
674         tochange->size = BAMBOO_SHARED_MEM_SIZE + BAMBOO_BASE_VA - gcheaptop;
675         // zero out all these spare memory
676         memset(tochange->ptr, '\0', tochange->size);
677         if(bamboo_free_mem_list->tail != tochange) {
678                 bamboo_free_mem_list->tail = tochange;
679                 if(bamboo_free_mem_list->tail != NULL) {
680                         RUNFREE(bamboo_free_mem_list->tail);
681                 }
682         }
683 } // void updateFreeMemList()
684
685 // enqueue root objs
686 inline void tomark(struct garbagelist * stackptr) {
687         if(MARKPHASE != gcphase) {
688                 BAMBOO_EXIT(0xb101);
689         }
690         gcbusystatus = true;
691         gcnumlobjs = 0;
692         
693         int i,j;
694         // enqueue current stack 
695         while(stackptr!=NULL) {
696 #ifdef GC_DEBUG
697                 BAMBOO_DEBUGPRINT(0xe501);
698                 BAMBOO_DEBUGPRINT_REG(stackptr->size);
699                 BAMBOO_DEBUGPRINT_REG(stackptr->next);
700                 BAMBOO_DEBUGPRINT_REG(stackptr->array[0]);
701 #endif
702                 for(i=0; i<stackptr->size; i++) {
703                         if(stackptr->array[i] != NULL) {
704                                 gc_enqueue(stackptr->array[i]);
705                         }
706                 }
707                 stackptr=stackptr->next;
708         }
709
710 #ifdef GC_DEBUG
711         BAMBOO_DEBUGPRINT(0xe503);
712 #endif
713         // enqueue objectsets
714         for(i=0; i<NUMCLASSES; i++) {
715                 struct parameterwrapper ** queues = 
716                         objectqueues[BAMBOO_NUM_OF_CORE][i];
717                 int length = numqueues[BAMBOO_NUM_OF_CORE][i];
718                 for(j = 0; j < length; ++j) {
719                         struct parameterwrapper * parameter = queues[j];
720                         struct ObjectHash * set=parameter->objectset;
721                         struct ObjectNode * ptr=set->listhead;
722                         while(ptr!=NULL) {
723                                 gc_enqueue((void *)ptr->key);
724                                 ptr=ptr->lnext;
725                         }
726                 }
727         }
728
729         // euqueue current task descriptor
730         if(currtpd != NULL) {
731 #ifdef GC_DEBUG
732                 BAMBOO_DEBUGPRINT(0xe504);
733 #endif
734                 for(i=0; i<currtpd->numParameters; i++) {
735                         gc_enqueue(currtpd->parameterArray[i]);
736                 }
737         }
738
739 #ifdef GC_DEBUG
740         BAMBOO_DEBUGPRINT(0xe505);
741 #endif
742         // euqueue active tasks
743         struct genpointerlist * ptr=activetasks->list;
744         while(ptr!=NULL) {
745                 struct taskparamdescriptor *tpd=ptr->src;
746                 int i;
747                 for(i=0; i<tpd->numParameters; i++) {
748                         gc_enqueue(tpd->parameterArray[i]);
749                 }
750                 ptr=ptr->inext;
751         }
752
753 #ifdef GC_DEBUG
754         BAMBOO_DEBUGPRINT(0xe506);
755 #endif
756         // enqueue cached transferred obj
757         struct QueueItem * tmpobjptr =  getHead(&objqueue);
758         while(tmpobjptr != NULL) {
759                 struct transObjInfo * objInfo = 
760                         (struct transObjInfo *)(tmpobjptr->objectptr); 
761                 gc_enqueue(objInfo->objptr);
762                 getNextQueueItem(tmpobjptr);
763         }
764 } // void tomark(struct garbagelist * stackptr)
765
766 inline void markObj(void * objptr) {
767         if(objptr == NULL) {
768                 return;
769         }
770         if(ISSHAREDOBJ(objptr)) {
771                 int host = hostcore(objptr);
772                 if(BAMBOO_NUM_OF_CORE == host) {
773                         // on this core
774                         gc_enqueue(objptr);  
775                 } else {
776                         // send a msg to host informing that objptr is active
777                         send_msg_2(host, GCMARKEDOBJ, objptr);
778                         gcself_numsendobjs++;
779                 }
780         } else {
781                 gc_enqueue(objptr);
782         } // if(ISSHAREDOBJ(objptr))
783 } // void markObj(void * objptr) 
784
785 inline void mark(bool isfirst, 
786                              struct garbagelist * stackptr) {
787         if(isfirst) {
788                 // enqueue root objs
789                 tomark(stackptr);
790                 gccurr_heaptop = 0; // record the size of all active objs in this core
791                                   // aligned but does not consider block boundaries
792                 gcmarkedptrbound = 0;
793         }
794         int isize = 0;
795         // mark phase
796         while(MARKPHASE == gcphase) {
797                 while(gc_moreItems2()) {
798                         gcbusystatus = true;
799                         void * ptr = gc_dequeue2();
800                         int size = 0;
801                         int isize = 0;
802                         int type = 0;
803                         // check if it is a shared obj
804                         if(ISSHAREDOBJ(ptr)) {
805                                 // a shared obj, check if it is a local obj on this core
806                                 if(isLarge(ptr, &type, &size)) {
807                                         // ptr is a large object
808                                         if(((int *)ptr)[6] == 0) {
809                                                 // not marked and not enqueued
810                                                 BAMBOO_START_CRITICAL_SECTION();
811                                                 gc_lobjenqueue(ptr, size, BAMBOO_NUM_OF_CORE);
812                                                 gcnumlobjs++;
813                                                 BAMBOO_CLOSE_CRITICAL_SECTION();
814                                                 // mark this obj
815                                                 ((int *)ptr)[6] = 1;
816                                         }
817                                 } else if ((isLocal(ptr)) && (((int *)ptr)[6] == 0)) {
818                                         // ptr is an unmarked active object on this core
819                                         ALIGNSIZE(size, &isize);
820                                         gccurr_heaptop += isize;
821 #ifdef GC_DEBUG
822                                         BAMBOO_DEBUGPRINT(0xaaaa);
823                                         BAMBOO_DEBUGPRINT_REG(ptr);
824                                         BAMBOO_DEBUGPRINT_REG(isize);
825 #endif
826                                         // mark this obj
827                                         ((int *)ptr)[6] = 1;
828                                         if(ptr + size > gcmarkedptrbound) {
829                                                 gcmarkedptrbound = ptr + size;
830                                         } // if(ptr + size > gcmarkedptrbound)
831                                 } // if(isLarge(ptr, &type, &size)) else if(isLocal(ptr))
832                         } // if(ISSHAREDOBJ(ptr))
833
834                         // scan all pointers in ptr
835                         unsigned INTPTR * pointer;
836                         pointer=pointerarray[type];
837                         if (pointer==0) {
838                                 /* Array of primitives */
839                                 /* Do nothing */
840                         } else if (((INTPTR)pointer)==1) {
841                                 /* Array of pointers */
842                                 struct ArrayObject *ao=(struct ArrayObject *) ptr;
843                                 int length=ao->___length___;
844                                 int j;
845                                 for(j=0; j<length; j++) {
846                                         void *objptr = 
847                                                 ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
848                                         markObj(objptr);
849                                 }
850                         } else {
851                                 INTPTR size=pointer[0];
852                                 int i;
853                                 for(i=1; i<=size; i++) {
854                                         unsigned int offset=pointer[i];
855                                         void * objptr=*((void **)(((char *)ptr)+offset));
856                                         markObj(objptr);
857                                 }
858                         }
859                 } // while(!isEmpty(gctomark))
860                 gcbusystatus = false;
861                 // send mark finish msg to core coordinator
862                 if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
863                         gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
864                         gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
865                         gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
866                         gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
867                 } else {
868                         send_msg_4(STARTUPCORE, GCFINISHMARK, BAMBOO_NUM_OF_CORE,
869                                                                  gcself_numsendobjs, gcself_numreceiveobjs);
870                 }
871
872                 if(BAMBOO_NUM_OF_CORE == 0) {
873                         return;
874                 }
875         } // while(MARKPHASE == gcphase)
876 } // mark()
877
878 inline void compact2Heaptop() {
879         // no cores with spare mem and some cores are blocked with pending move
880         // find the current heap top and make them move to the heap top
881         int p;
882         int numblocks = gcfilledblocks[gctopcore];
883         BASEPTR(gctopcore, numblocks, &p);
884         int b;
885         BLOCKINDEX(p, &b);
886         int remain = b<NUMCORES ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
887         if((gctopcore == STARTUPCORE) && (b == 0)) {
888                 remain -= gcreservedsb*BAMBOO_SMEM_SIZE;
889                 p += gcreservedsb*BAMBOO_SMEM_SIZE;
890         }
891         for(int i = 0; i < NUMCORES; i++) {
892                 if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0)) {
893                         int memneed = gcrequiredmems[i] + BAMBOO_CACHE_LINE_SIZE;
894                         if(STARTUPCORE == i) {
895                                 gctomove = true;
896                                 gcmovestartaddr = p;
897                                 gcdstcore = gctopcore;
898                                 gcblock2fill = numblocks + 1;
899                         } else {
900                                 send_msg_4(i, GCMOVESTART, gctopcore, p, numblocks + 1);
901                         }
902                         if(memneed < remain) {
903                                 p += memneed;
904                                 gcrequiredmems[i] = 0;
905                                 gcmovepending--;
906                                 gcloads[gctopcore] += memneed;
907                         } else {
908                                 // next available block
909                                 p += remain;
910                                 gcfilledblocks[gctopcore] += 1;
911                                 int newbase = 0;
912                                 BASEPTR(gctopcore, gcfilledblocks[gctopcore], &newbase);
913                                 gcloads[gctopcore] = newbase;
914                                 gcrequiredmems[i] -= remain - BAMBOO_CACHE_LINE_SIZE;
915                                 gcstopblock[gctopcore]++;
916                                 if(gcheapdirection) {
917                                         gctopcore++;
918                                         if(gctopcore== NUMCORES) {
919                                                 gctopcore--;
920                                                 gcheapdirection = false;
921                                         }
922                                 } else {
923                                         gctopcore--;
924                                         if(gctopcore < 0) {
925                                                 gctopcore++;
926                                                 gcheapdirection = true;
927                                         }
928                                 }
929                                 numblocks = gcstopblock[gctopcore];
930                                 BASEPTR(gctopcore, numblocks, &p);
931                                 BLOCKINDEX(p, &p);
932                                 remain = b<NUMCORES ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
933                         } // if(memneed < remain)
934                 } // if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0))
935         } // for(i = 0; i < NUMCORES; i++)
936 } // void compact2Heaptop()
937
938 inline void resolvePendingMoveRequest() {
939         int i;
940         int j;
941         bool nosparemem = true;
942         bool haspending = false;
943         bool hasrunning = false;
944         bool noblock = false;
945         int dstcore = 0;
946         int sourcecore = 0;
947         for(i = j = 0; (i < NUMCORES) && (j < NUMCORES);) {
948                 if(nosparemem) {
949                         // check if there are cores with spare mem
950                         if(gccorestatus[i] == 0) {
951                                 // finished working, check if it still have spare mem
952                                 if(gcfilledblocks[i] < gcstopblock[i]) {
953                                         // still have spare mem
954                                         nosparemem = false;
955                                         dstcore = i;
956                                 } // if(gcfilledblocks[i] < gcstopblock[i]) else ...
957                         }
958                         i++;
959                 } // if(nosparemem)
960                 if(!haspending) {
961                         if(gccorestatus[j] != 0) {
962                                 // not finished, check if it has pending move requests
963                                 if((gcfilledblocks[j]==gcstopblock[j])&&(gcrequiredmems[j]>0)) {
964                                         sourcecore = j;
965                                         haspending = true;
966                                 } else {
967                                         hasrunning = true;
968                                 } // if((gcfilledblocks[i] == gcstopblock[i])...) else ...
969                         } // if(gccorestatus[i] == 0) else ...
970                         j++;
971                 } // if(!haspending)
972                 if(!nosparemem && haspending) {
973                         // find match
974                         int tomove = 0;
975                         int startaddr = 0;
976                         gcrequiredmems[dstcore] = assignSpareMem(sourcecore, 
977                                                                              gcrequiredmems[dstcore], 
978                                                                                                                                                                                          &tomove, 
979                                                                                                                                                                                          &startaddr);
980                         if(STARTUPCORE == dstcore) {
981                                 gcdstcore = sourcecore;
982                                 gctomove = true;
983                                 gcmovestartaddr = startaddr;
984                                 gcblock2fill = tomove;
985                         } else {
986                                 send_msg_4(dstcore, GCMOVESTART, sourcecore, startaddr, tomove);
987                         }
988                         if(gcrequiredmems[dstcore] == 0) {
989                                 gcmovepending--;
990                         }
991                         nosparemem = true;
992                         haspending = false;
993                         noblock = true;
994                 }
995         } // for(i = 0; i < NUMCORES; i++)
996 #ifdef GCDEBUG
997         BAMBOO_DEBUGPRINT(0xcccc);
998         BAMBOO_DEBUGPRINT_REG(hasrunning);
999         BAMBOO_DEBUGPRINT_REG(haspending);
1000         BAMBOO_DEBUGPRINT_REG(noblock);
1001 #endif
1002
1003         if(!hasrunning && !noblock) {
1004                 gcphase = SUBTLECOMPACTPHASE;
1005                 compact2Heaptop();
1006         }
1007
1008 } // void resovePendingMoveRequest()
1009
1010 struct moveHelper {
1011         int numblocks; // block num for heap
1012         INTPTR base; // base virtual address of current heap block
1013         INTPTR ptr; // virtual address of current heap top
1014         int offset; // offset in current heap block
1015         int blockbase; // virtual address of current small block to check
1016         int blockbound; // bound virtual address of current small blcok
1017         int sblockindex; // index of the small blocks
1018         int top; // real size of current heap block to check
1019         int bound; // bound size of current heap block to check
1020 }; // struct moveHelper
1021
1022 inline void nextSBlock(struct moveHelper * orig) {
1023         orig->blockbase = orig->blockbound;
1024 innernextSBlock:
1025         if(orig->blockbase >= orig->bound) {
1026                 // end of current heap block, jump to next one
1027                 orig->numblocks++;
1028                 BASEPTR(BAMBOO_NUM_OF_CORE, orig->numblocks, &(orig->base));
1029                 orig->bound = orig->base + BAMBOO_SMEM_SIZE;
1030                 orig->blockbase = orig->base;
1031         }
1032         orig->sblockindex = (orig->blockbase-BAMBOO_BASE_VA)/BAMBOO_SMEM_SIZE;
1033         if(gcsbstarttbl[orig->sblockindex] == -1) {
1034                 // goto next sblock
1035                 orig->sblockindex += 1;
1036                 orig->blockbase += BAMBOO_SMEM_SIZE;
1037                 goto innernextSBlock;
1038         } else if(gcsbstarttbl[orig->sblockindex] != 0) {
1039                 // not start from the very beginning
1040                 orig->blockbase = gcsbstarttbl[orig->sblockindex];
1041         }
1042         orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1043         orig->offset = BAMBOO_CACHE_LINE_SIZE;
1044         orig->ptr = orig->blockbase + orig->offset;
1045 } // void nextSBlock(struct moveHelper * orig) 
1046
1047 inline void initOrig_Dst(struct moveHelper * orig, 
1048                                      struct moveHelper * to) {
1049         // init the dst ptr
1050         to->numblocks = 0;
1051         to->top = to->offset = BAMBOO_CACHE_LINE_SIZE;
1052         to->bound = BAMBOO_SMEM_SIZE_L;
1053         BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1054         if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1055                 to->base += gcreservedsb * BAMBOO_SMEM_SIZE;
1056                 to->top += gcreservedsb * BAMBOO_SMEM_SIZE;
1057         }
1058         to->ptr = to->base + to->offset;
1059
1060         // init the orig ptr
1061         orig->numblocks = 0;
1062         orig->base = to->base;
1063         orig->bound = to->base + BAMBOO_SMEM_SIZE_L;
1064         orig->blockbase = orig->base;
1065         if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1066                 orig->sblockindex = gcreservedsb;
1067         } else {
1068                 orig->sblockindex = (orig->base - BAMBOO_BASE_VA) / BAMBOO_SMEM_SIZE;
1069         }
1070         if(gcsbstarttbl[orig->sblockindex] == -1) {
1071                 // goto next sblock
1072                 orig->blockbound = 
1073                         BAMBOO_BASE_VA+BAMBOO_SMEM_SIZE*(orig->sblockindex+1);
1074                 nextSBlock(orig);
1075                 return;
1076         } else if(gcsbstarttbl[orig->sblockindex] != 0) {
1077                 orig->blockbase = gcsbstarttbl[orig->sblockindex];
1078         }
1079         orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1080         orig->offset = BAMBOO_CACHE_LINE_SIZE;
1081         orig->ptr = orig->blockbase + orig->offset;
1082 } // void initOrig_Dst(struct moveHelper * orig, struct moveHelper * to) 
1083
1084 inline void nextBlock(struct moveHelper * to) {
1085         to->top = to->bound + BAMBOO_CACHE_LINE_SIZE; // header!
1086         to->bound += BAMBOO_SMEM_SIZE;
1087         to->numblocks++;
1088         BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1089         to->offset = BAMBOO_CACHE_LINE_SIZE;
1090         to->ptr = to->base + to->offset;
1091 } // void nextBlock(struct moveHelper * to)
1092
1093 // endaddr does not contain spaces for headers
1094 inline bool moveobj(struct moveHelper * orig, 
1095                                 struct moveHelper * to, 
1096                                                         int stopblock) {
1097         if(stopblock == 0) {
1098                 return true;
1099         }
1100
1101 #ifdef GC_DEBUG
1102         BAMBOO_DEBUGPRINT(0xe201);
1103         BAMBOO_DEBUGPRINT_REG(orig->ptr);
1104         BAMBOO_DEBUGPRINT_REG(to->ptr);
1105 #endif
1106
1107         int type = 0;
1108         int size = 0;
1109         int mark = 0;
1110         int isize = 0;
1111 innermoveobj:
1112         while((char)(*((int*)(orig->ptr))) == (char)(-2)) {
1113                 orig->ptr++;
1114                 if((orig->ptr > orig->bound) || (orig->ptr == orig->blockbound)) {
1115                         nextSBlock(orig);
1116                         goto innermoveobj;
1117                 }
1118         }
1119 #ifdef GC_DEBUG
1120         BAMBOO_DEBUGPRINT(0xe202);
1121 #endif
1122         // check the obj's type, size and mark flag
1123         type = ((int *)(orig->ptr))[0];
1124         size = 0;
1125         if(type == -1) {
1126                 // end of this block, go to next one
1127                 nextSBlock(orig);
1128                 goto innermoveobj;
1129         } else if(type < NUMCLASSES) {
1130                 // a normal object
1131                 size = classsize[type];
1132         } else {        
1133                 // an array 
1134                 struct ArrayObject *ao=(struct ArrayObject *)(orig->ptr);
1135                 int elementsize=classsize[type];
1136                 int length=ao->___length___; 
1137                 size=sizeof(struct ArrayObject)+length*elementsize;
1138         }
1139         mark = ((int *)(orig->ptr))[6];
1140 #ifdef GC_DEBUG
1141         BAMBOO_DEBUGPRINT(0xe203);
1142 #endif
1143         if(mark == 1) {
1144 #ifdef GC_DEBUG
1145                 BAMBOO_DEBUGPRINT(0xe204);
1146 #endif
1147                 // marked obj, copy it to current heap top
1148                 // check to see if remaining space is enough
1149                 ALIGNSIZE(size, &isize);
1150                 if(to->top + isize > to->bound) {
1151                         // fill -1 indicating the end of this block
1152                         if(to->top != to->bound) {
1153                                 *((int*)to->ptr) = -1;
1154                         }
1155                         //memset(to->ptr+1,  -2, to->bound - to->top - 1);
1156                         // fill the header of this block and then go to next block
1157         to->offset += to->bound - to->top;
1158                         (*((int*)(to->base))) = to->offset;
1159                         nextBlock(to);
1160                         if(stopblock == to->numblocks) {
1161                                 // already fulfilled the block
1162                                 to->offset = 0;
1163                                 to->ptr = to->base;
1164                                 return true;
1165                         }
1166                 }
1167                 memcpy(to->ptr, orig->ptr, size);
1168                 // fill the remaining space with -2
1169                 memset(to->ptr+size, -2, isize-size);
1170                 // store mapping info
1171                 BAMBOO_START_CRITICAL_SECTION();
1172                 RuntimeHashadd(gcpointertbl, orig->ptr, to->ptr); 
1173                 BAMBOO_CLOSE_CRITICAL_SECTION();
1174                 gccurr_heaptop -= isize;
1175                 to->ptr += isize;
1176                 to->offset += isize;
1177                 to->top += isize;
1178         }
1179 #ifdef GC_DEBUG
1180         BAMBOO_DEBUGPRINT(0xe205);
1181 #endif
1182         // move to next obj
1183         orig->ptr += size;
1184         if((orig->ptr > orig->bound) || (orig->ptr == orig->blockbound)) {
1185                 nextSBlock(orig);
1186         }
1187         return false;
1188 } //bool moveobj(struct moveHelper* orig,struct moveHelper* to,int* endaddr)
1189
1190 inline int assignSpareMem(int sourcecore,
1191                                        int * requiredmem,
1192                                                                                                          int * tomove,
1193                                                                                                          int * startaddr) {
1194         int b = 0;
1195         BLOCKINDEX(gcloads[sourcecore], &b);
1196         int boundptr = b<NUMCORES?(b+1)*BAMBOO_SMEM_SIZE_L
1197                 :BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES+1)*BAMBOO_SMEM_SIZE;
1198         int remain = boundptr - gcloads[sourcecore];
1199         int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
1200         *startaddr = gcloads[sourcecore];
1201         *tomove = gcfilledblocks[sourcecore] + 1;
1202         if(memneed < remain) {
1203                 gcloads[sourcecore] += memneed;
1204                 return 0;
1205         } else {
1206                 // next available block
1207                 gcfilledblocks[sourcecore] += 1;
1208                 int newbase = 0;
1209                 BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
1210                 gcloads[sourcecore] = newbase;
1211                 return requiredmem-remain;
1212         }
1213 }
1214
1215 inline bool gcfindSpareMem(int * startaddr,
1216                                        int * tomove,
1217                                                                                                  int * dstcore,
1218                                                                                                  int requiredmem,
1219                                                                                                  int requiredcore) {
1220         for(int k = 0; k < NUMCORES; k++) {
1221                 if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
1222                         // check if this stopped core has enough mem
1223                         assignSpareMem(k, requiredmem, tomove, startaddr);
1224                         *dstcore = k;
1225                         return true;
1226                 }
1227         }
1228         // if can not find spare mem right now, hold the request
1229         gcrequiredmems[requiredcore] = requiredmem;
1230         gcmovepending++;
1231         return false;
1232 } //bool gcfindSpareMem(int* startaddr,int* tomove,int mem,int core)
1233
1234 inline bool compacthelper(struct moveHelper * orig,
1235                                       struct moveHelper * to,
1236                                                                                                         int * filledblocks,
1237                                                                                                         int * heaptopptr,
1238                                                                                                         bool * localcompact) {
1239         // scan over all objs in this block, compact the marked objs 
1240         // loop stop when finishing either scanning all active objs or 
1241         // fulfilled the gcstopblock
1242 innercompact:
1243         do {
1244                 bool stop = moveobj(orig, to, gcblock2fill);
1245                 if(stop) {
1246                         break;
1247                 }
1248         } while(orig->ptr < gcmarkedptrbound);
1249         // if no objs have been compact, do nothing, 
1250         // otherwise, fill the header of this block
1251         if(to->offset > BAMBOO_CACHE_LINE_SIZE) {
1252                 (*((int*)(to->base))) = to->offset;
1253         } else {
1254                 to->offset = 0;
1255                 to->ptr = to->base;
1256                 to->top -= BAMBOO_CACHE_LINE_SIZE;
1257         } // if(to->offset > BAMBOO_CACHE_LINE_SIZE) else ...
1258         if(*localcompact) {
1259                 *heaptopptr = to->ptr;
1260                 *filledblocks = to->numblocks;
1261         }
1262 #ifdef GC_DEBUG
1263         BAMBOO_DEBUGPRINT(0xe101);
1264         BAMBOO_DEBUGPRINT_REG(*heaptopptr);
1265         BAMBOO_DEBUGPRINT_REG(*filledblocks);
1266 #endif
1267
1268         // send msgs to core coordinator indicating that the compact is finishing
1269         // send compact finish message to core coordinator
1270         if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1271                 gcfilledblocks[BAMBOO_NUM_OF_CORE] = *filledblocks;
1272                 gcloads[BAMBOO_NUM_OF_CORE] = *heaptopptr;
1273                 if(orig->ptr < gcmarkedptrbound) {
1274                         // ask for more mem
1275                         gctomove = false;
1276                         if(gcfindSpareMem(&gcmovestartaddr, &gcblock2fill, &gcdstcore, 
1277                                                             gccurr_heaptop, BAMBOO_NUM_OF_CORE)) {
1278                                 gctomove = true;
1279                         } else {
1280                                 return false; 
1281                         }
1282                 } else {
1283                         gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1284                         return true;
1285                 }
1286         } else {
1287                 if(orig->ptr < gcmarkedptrbound) {
1288                         // ask for more mem
1289                         gctomove = false;
1290                         send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE, 
1291                                                *filledblocks, *heaptopptr, gccurr_heaptop);
1292                 } else {
1293                         // finish compacting
1294                         send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
1295                                                *filledblocks, *heaptopptr, 0);
1296                 }
1297         } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
1298
1299         if(orig->ptr < gcmarkedptrbound) {
1300                 // still have unpacked obj
1301                 while(!gctomove) {};
1302                 gctomove = false;
1303
1304                 to->ptr = gcmovestartaddr;
1305                 to->numblocks = gcblock2fill - 1;
1306                 to->bound = (to->numblocks==0)?
1307                         BAMBOO_SMEM_SIZE_L:
1308                         BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
1309                 BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1310                 to->offset = to->ptr - to->base;
1311                 to->top = (to->numblocks==0)?
1312                         (to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
1313                 to->base = to->ptr;
1314                 to->offset = BAMBOO_CACHE_LINE_SIZE;
1315                 to->ptr += to->offset; // for header
1316                 to->top += to->offset;
1317                 if(gcdstcore == BAMBOO_NUM_OF_CORE) {
1318                         *localcompact = true;
1319                 } else {
1320                         *localcompact = false;
1321                 }
1322                 goto innercompact;
1323         }
1324         return true;
1325 } // void compacthelper()
1326
1327 inline void compact() {
1328         if(COMPACTPHASE != gcphase) {
1329                 BAMBOO_EXIT(0xb102);
1330         }
1331
1332         // initialize pointers for comapcting
1333         struct moveHelper * orig = 
1334                 (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1335         struct moveHelper * to = 
1336                 (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1337
1338         initOrig_Dst(orig, to);
1339         
1340         int filledblocks = 0;
1341         INTPTR heaptopptr = 0;
1342         bool localcompact = true;
1343         compacthelper(orig, to, &filledblocks, &heaptopptr, &localcompact);
1344
1345         RUNFREE(orig);
1346         RUNFREE(to);
1347 } // compact()
1348
1349 inline void * flushObj(void * objptr) {
1350 #ifdef GC_DEBUG
1351         BAMBOO_DEBUGPRINT(0xe401);
1352 #endif
1353         void * dstptr = NULL;
1354         if(ISSHAREDOBJ(objptr)) {
1355 #ifdef GC_DEBUG
1356                 BAMBOO_DEBUGPRINT(0xe402);
1357                 BAMBOO_DEBUGPRINT_REG(objptr);
1358 #endif
1359                 // a shared obj ptr, change to new address
1360                 BAMBOO_START_CRITICAL_SECTION();
1361                 RuntimeHashget(gcpointertbl, objptr, &dstptr);
1362                 BAMBOO_CLOSE_CRITICAL_SECTION();
1363                 if(NULL == dstptr) {
1364 #ifdef GC_DEBUG
1365                         BAMBOO_DEBUGPRINT(0xe403);
1366 #endif
1367                         // send msg to host core for the mapping info
1368                         gcobj2map = (int)objptr;
1369                         gcismapped = false;
1370                         gcmappedobj = NULL;
1371                         send_msg_3(hostcore(objptr), GCMAPREQUEST, (int)objptr, 
1372                                                                  BAMBOO_NUM_OF_CORE);
1373                         while(!gcismapped) {}
1374                         BAMBOO_START_CRITICAL_SECTION();
1375                         RuntimeHashget(gcpointertbl, objptr, &dstptr);
1376                         BAMBOO_CLOSE_CRITICAL_SECTION();
1377                 }
1378         } // if(ISSHAREDOBJ(objptr))
1379 #ifdef GC_DEBUG
1380         BAMBOO_DEBUGPRINT(0xe404);
1381 #endif
1382         return dstptr;
1383 } // void flushObj(void * objptr, void ** tochange)
1384
1385 inline void flush() {
1386         while(gc_moreItems()) {
1387 #ifdef GC_DEBUG
1388                 BAMBOO_DEBUGPRINT(0xe301);
1389 #endif
1390                 void * ptr = gc_dequeue();
1391 #ifdef GC_DEBUG
1392                 BAMBOO_DEBUGPRINT_REG(ptr);
1393 #endif
1394                 if(((int *)(ptr))[6] == 1) {
1395                         void * tptr = flushObj(ptr);
1396 #ifdef GC_DEBUG
1397                         BAMBOO_DEBUGPRINT(0xe302);
1398 #endif
1399                         if(tptr != NULL) {
1400                                 ptr = tptr;
1401                         }
1402                         int type = ((int *)(ptr))[0];
1403                         // scan all pointers in ptr
1404                         unsigned INTPTR * pointer;
1405                         pointer=pointerarray[type];
1406 #ifdef GC_DEBUG
1407                         BAMBOO_DEBUGPRINT(0xe303);
1408 #endif
1409                         if (pointer==0) {
1410                                 /* Array of primitives */
1411                                 /* Do nothing */
1412                         } else if (((INTPTR)pointer)==1) {
1413 #ifdef GC_DEBUG
1414                                 BAMBOO_DEBUGPRINT(0xe304);
1415 #endif
1416                                 /* Array of pointers */
1417                                 struct ArrayObject *ao=(struct ArrayObject *) ptr;
1418                                 int length=ao->___length___;
1419                                 int j;
1420                                 for(j=0; j<length; j++) {
1421 #ifdef GC_DEBUG
1422                                         BAMBOO_DEBUGPRINT(0xe305);
1423 #endif
1424                                         void *objptr=
1425                                                 ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
1426 #ifdef GC_DEBUG
1427                                         BAMBOO_DEBUGPRINT_REG(objptr);
1428 #endif
1429                                         ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] = 
1430                                                 flushObj(objptr);
1431                                 }
1432                         } else {
1433 #ifdef GC_DEBUG
1434                                 BAMBOO_DEBUGPRINT(0xe306);
1435 #endif
1436                                 INTPTR size=pointer[0];
1437                                 int i;
1438                                 for(i=1; i<=size; i++) {
1439 #ifdef GC_DEBUG
1440                                         BAMBOO_DEBUGPRINT(0xe307);
1441 #endif
1442                                         unsigned int offset=pointer[i];
1443                                         void * objptr=*((void **)(((char *)ptr)+offset));
1444 #ifdef GC_DEBUG
1445                                         BAMBOO_DEBUGPRINT_REG(objptr);
1446 #endif
1447                                         *((void **)(((char *)ptr)+offset)) = flushObj(objptr);
1448                                 } // for(i=1; i<=size; i++) 
1449                         } // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
1450                         // restore the mark field, indicating that this obj has been flushed
1451                         ((int *)(ptr))[6] = 0;
1452                 } // if(((int *)(ptr))[6] == 1)
1453         } // while(moi != NULL)
1454 #ifdef GC_DEBUG
1455         BAMBOO_DEBUGPRINT(0xe308);
1456 #endif
1457         // send flush finish message to core coordinator
1458         if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1459                 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1460         } else {
1461                 send_msg_2(STARTUPCORE, GCFINISHFLUSH, BAMBOO_NUM_OF_CORE);
1462         }
1463 #ifdef GC_DEBUG
1464         BAMBOO_DEBUGPRINT(0xe309);
1465 #endif
1466 } // flush()
1467
1468 inline void gc_collect(struct garbagelist * stackptr) {
1469         // core collector routine
1470         mark(true, stackptr);
1471         compact();
1472         while(FLUSHPHASE != gcphase) {}
1473         flush();
1474
1475         while(FINISHPHASE != gcphase) {}
1476 } // void gc_collect(struct garbagelist * stackptr)
1477
1478 inline void gc(struct garbagelist * stackptr) {
1479         // check if do gc
1480         if(!gcflag) {
1481                 return;
1482         }
1483
1484         // core coordinator routine
1485         if(0 == BAMBOO_NUM_OF_CORE) {
1486                 if(!preGC()) {
1487                         // not ready to do gc
1488                         gcflag = true;
1489                         return;
1490                 }
1491
1492 #ifdef GC_DEBUG
1493                 tprintf("start gc! \n");
1494                 dumpSMem();
1495 #endif
1496
1497                 initGC();
1498
1499                 gcprocessing = true;
1500                 int i = 0;
1501                 waitconfirm = false;
1502                 waitconfirm = 0;
1503                 gcphase = MARKPHASE;
1504                 for(i = 1; i < NUMCORES - 1; i++) {
1505                         // send GC start messages to all cores
1506                         send_msg_1(i, GCSTART);
1507                 }
1508                 bool isfirst = true;
1509                 bool allStall = false;
1510
1511                 // mark phase
1512                 while(MARKPHASE == gcphase) {
1513                         mark(isfirst, stackptr);
1514                         if(isfirst) {
1515                                 isfirst = false;
1516                         }
1517
1518                         // check gcstatus
1519                         checkMarkStatue(); 
1520                 }  // while(MARKPHASE == gcphase)
1521                 // send msgs to all cores requiring large objs info
1522                 numconfirm = NUMCORES - 1;
1523                 for(i = 1; i < NUMCORES; ++i) {
1524                         send_msg_1(i, GCLOBJREQUEST);
1525                 }
1526                 gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
1527                 while(numconfirm != 0) {} // wait for responses
1528 #ifdef GC_DEBUG
1529                 tprintf("prepare to cache large objs \n");
1530                 dumpSMem();
1531 #endif
1532                 // cache all large objs
1533                 if(!cacheLObjs()) {
1534                         // no enough space to cache large objs
1535                         BAMBOO_EXIT(0xb103);
1536                 }
1537                 // predict number of blocks to fill for each core
1538                 int numpbc = loadbalance();
1539                 for(i = 0; i < NUMCORES; ++i) {
1540                         //send start compact messages to all cores
1541                         if((gcheapdirection) && (i < gctopcore)
1542                                         || ((!gcheapdirection) && (i > gctopcore))) {
1543                                 gcstopblock[i] =numpbc + 1;
1544                                 if(i != STARTUPCORE) {
1545                                         send_msg_2(i, GCSTARTCOMPACT, numpbc+1); 
1546                                 }
1547                         } else {
1548                                 gcstopblock[i] = numpbc;
1549                                 if(i != STARTUPCORE) {
1550                                         send_msg_2(i, GCSTARTCOMPACT, numpbc);
1551                                 }
1552                         }
1553                         // init some data strutures for compact phase
1554                         gcloads[i] = 0;
1555                         gcfilledblocks[i] = 0;
1556                         gcrequiredmems[i] = 0;
1557                 }
1558 #ifdef GC_DEBUG
1559                 tprintf("mark phase finished \n");
1560                 dumpSMem();
1561 #endif
1562
1563                 // compact phase
1564                 bool finalcompact = false;
1565                 // initialize pointers for comapcting
1566                 struct moveHelper * orig = 
1567                         (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1568                 struct moveHelper * to = 
1569                         (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
1570                 initOrig_Dst(orig, to);
1571                 int filledblocks = 0;
1572                 INTPTR heaptopptr = 0;
1573                 bool finishcompact = false;
1574                 bool iscontinue = true;
1575                 bool localcompact = true;
1576                 while((COMPACTPHASE == gcphase) || (SUBTLECOMPACTPHASE == gcphase)) {
1577                         if((!finishcompact) && iscontinue) {
1578 #ifdef GC_DEBUG
1579                                 BAMBOO_DEBUGPRINT(0xe001);
1580 #endif
1581                                 finishcompact = compacthelper(orig, to, &filledblocks, 
1582                                                                           &heaptopptr, &localcompact);
1583 #ifdef GC_DEBUG
1584                                 BAMBOO_DEBUGPRINT_REG(finishcompact);
1585                                 BAMBOO_DEBUGPRINT_REG(gctomove);
1586                                 BAMBOO_DEBUGPRINT_REG(gcrequiredmems[0]);
1587                                 BAMBOO_DEBUGPRINT_REG(gcfilledblocks[0]);
1588                                 BAMBOO_DEBUGPRINT_REG(gcstopblock[0]);
1589 #endif
1590                         }
1591
1592                         if(gc_checkCoreStatus()) {
1593                                 // all cores have finished compacting
1594                                 // restore the gcstatus of all cores
1595                                 for(i = 0; i < NUMCORES; ++i) {
1596                                         gccorestatus[i] = 1;
1597                                 }
1598                                 break;
1599                         } else {
1600                                 // check if there are spare mem for pending move requires
1601                                 if(COMPACTPHASE == gcphase) {
1602                                         resolvePendingMoveRequest();
1603                                 } else {
1604 #ifdef GC_DEBUG
1605                                         BAMBOO_DEBUGPRINT(0xe002);
1606 #endif
1607                                         compact2Heaptop();
1608                                 }
1609                         } // if(gc_checkCoreStatus()) else ...
1610
1611                         if(gctomove) {
1612 #ifdef GC_DEBUG
1613                                 BAMBOO_DEBUGPRINT(0xe003);
1614                                 BAMBOO_DEBUGPRINT_REG(gcmovestartaddr);
1615                                 BAMBOO_DEBUGPRINT_REG(gcblock2fill);
1616                                 BAMBOO_DEBUGPRINT_REG(gctomove);
1617 #endif
1618                                 to->ptr = gcmovestartaddr;
1619                                 to->numblocks = gcblock2fill - 1;
1620                                 to->bound = (to->numblocks==0)?
1621                                         BAMBOO_SMEM_SIZE_L:
1622                                         BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
1623                                 BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1624                                 to->offset = to->ptr - to->base;
1625                                 to->top = (to->numblocks==0)?
1626                                         (to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
1627                                 to->base = to->ptr;
1628                                 to->offset = BAMBOO_CACHE_LINE_SIZE;
1629                                 to->ptr += to->offset; // for header
1630                                 to->top += to->offset;
1631                                 if(gcdstcore == BAMBOO_NUM_OF_CORE) {
1632                                         localcompact = true;
1633                                 } else {
1634                                         localcompact = false;
1635                                 }
1636                                 gctomove = false;
1637                                 iscontinue = true;
1638                         } else if(!finishcompact) {
1639                                 // still pending
1640                                 iscontinue = false;
1641                         } // if(gctomove)
1642
1643                 } // while(COMPACTPHASE == gcphase) 
1644 #ifdef GC_DEBUG
1645                 tprintf("prepare to move large objs \n");
1646                 dumpSMem();
1647 #endif
1648                 // move largeObjs
1649                 moveLObjs();
1650 #ifdef GC_DEBUG
1651                 tprintf("compact phase finished \n");
1652                 dumpSMem();
1653 #endif
1654
1655                 gcphase = FLUSHPHASE;
1656                 for(i = 1; i < NUMCORES; ++i) {
1657                         // send start flush messages to all cores
1658                         send_msg_1(i, GCSTARTFLUSH);
1659                 }
1660
1661                 // flush phase
1662                 flush();
1663                 gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1664                 while(FLUSHPHASE == gcphase) {
1665                         // check the status of all cores
1666                         allStall = true;
1667                         for(i = 0; i < NUMCORES; ++i) {
1668                                 if(gccorestatus[i] != 0) {
1669                                         allStall = false;
1670                                         break;
1671                                 }
1672                         }       
1673                         if(allStall) {
1674                                 break;
1675                         }
1676                 } // while(FLUSHPHASE == gcphase)
1677                 gcphase = FINISHPHASE;
1678                 for(i = 1; i < NUMCORES; ++i) {
1679                         // send gc finish messages to all cores
1680                         send_msg_1(i, GCFINISH);
1681                 }
1682 #ifdef GC_DEBUG
1683                 tprintf("flush phase finished \n");
1684                 dumpSMem();
1685 #endif
1686
1687                 // need to create free memory list  
1688                 updateFreeMemList();
1689 #ifdef GC_DEBUG
1690                 tprintf("gc finished \n");
1691                 dumpSMem();
1692 #endif
1693         } else {
1694                 gcprocessing = true;
1695                 gc_collect(stackptr);
1696         }
1697
1698         // invalidate all shared mem pointers
1699         bamboo_cur_msp = NULL;
1700         bamboo_smem_size = 0;
1701
1702         gcflag = false;
1703         gcprocessing = false;
1704
1705 } // void gc(struct garbagelist * stackptr)
1706
1707 #endif