tweak to interface
[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 #include "GCSharedHash.h"
10
11 // TODO for profiling the flush phase
12 #ifdef GC_PROFILE
13 int num_mapinforequest;
14 int num_markrequest;
15 unsigned long long marktime;
16 #endif
17
18 extern int corenum;
19 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
20 extern int numqueues[][NUMCLASSES];
21
22 extern struct genhashtable * activetasks;
23 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
24 extern struct taskparamdescriptor *currtpd;
25
26 extern struct LockValue runtime_locks[MAXTASKPARAMS];
27 extern int runtime_locklen;
28
29 struct pointerblock {
30   void * ptrs[NUMPTRS];
31   struct pointerblock *next;
32 };
33
34 struct pointerblock *gchead=NULL;
35 int gcheadindex=0;
36 struct pointerblock *gctail=NULL;
37 int gctailindex=0;
38 struct pointerblock *gctail2=NULL;
39 int gctailindex2=0;
40 struct pointerblock *gcspare=NULL;
41
42 #define NUMLOBJPTRS 20
43
44 struct lobjpointerblock {
45   void * lobjs[NUMLOBJPTRS];
46   //void * dsts[NUMLOBJPTRS];
47   int lengths[NUMLOBJPTRS];
48   //void * origs[NUMLOBJPTRS];
49   int hosts[NUMLOBJPTRS];
50   struct lobjpointerblock *next;
51   struct lobjpointerblock *prev;
52 };
53
54 struct lobjpointerblock *gclobjhead=NULL;
55 int gclobjheadindex=0;
56 struct lobjpointerblock *gclobjtail=NULL;
57 int gclobjtailindex=0;
58 struct lobjpointerblock *gclobjtail2=NULL;
59 int gclobjtailindex2=0;
60 struct lobjpointerblock *gclobjspare=NULL;
61
62 #ifdef GC_DEBUG
63 // dump whole mem in blocks
64 inline void dumpSMem() {
65   int block = 0;
66   int sblock = 0;
67   int j = 0;
68   int i = 0;
69   int coren = 0;
70   int x = 0;
71   int y = 0;
72   printf("(%x,%x) Dump shared mem: \n", udn_tile_coord_x(), 
73              udn_tile_coord_y());
74   // reserved blocks for sblocktbl
75   printf("(%x,%x) ++++ reserved sblocks ++++ \n", udn_tile_coord_x(), 
76              udn_tile_coord_y());
77   for(i=BAMBOO_BASE_VA; i<gcbaseva; i+= 4*16) {
78     printf("(%x,%x) 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",
79                    udn_tile_coord_x(), udn_tile_coord_y(),
80            *((int *)(i)), *((int *)(i + 4)),
81            *((int *)(i + 4*2)), *((int *)(i + 4*3)),
82            *((int *)(i + 4*4)), *((int *)(i + 4*5)),
83            *((int *)(i + 4*6)), *((int *)(i + 4*7)),
84            *((int *)(i + 4*8)), *((int *)(i + 4*9)),
85            *((int *)(i + 4*10)), *((int *)(i + 4*11)),
86            *((int *)(i + 4*12)), *((int *)(i + 4*13)),
87            *((int *)(i + 4*14)), *((int *)(i + 4*15)));
88   }
89   sblock = gcreservedsb;
90   bool advanceblock = false;
91   // remaining memory
92   for(i=gcbaseva; i<BAMBOO_BASE_VA+BAMBOO_SHARED_MEM_SIZE; i+=4*16) {
93     advanceblock = false;
94     // computing sblock # and block #, core coordinate (x,y) also
95     if(j%((BAMBOO_SMEM_SIZE)/(4*16)) == 0) {
96       // finished a sblock
97       if(j < ((BAMBOO_LARGE_SMEM_BOUND)/(4*16))) {
98         if((j > 0) && (j%((BAMBOO_SMEM_SIZE_L)/(4*16)) == 0)) {
99           // finished a block
100           block++;
101           advanceblock = true;
102         }
103       } else {
104         // finished a block
105         block++;
106         advanceblock = true;
107       }
108       // compute core #
109       if(advanceblock) {
110         coren = gc_block2core[block%(NUMCORES4GC*2)];
111       }
112       // compute core coordinate
113       BAMBOO_COORDS(coren, &x, &y);
114       printf("(%x,%x) ==== %d, %d : core (%d,%d), saddr %x====\n",
115                      udn_tile_coord_x(), udn_tile_coord_y(),
116              block, sblock++, x, y,
117              (sblock-1)*(BAMBOO_SMEM_SIZE)+BAMBOO_BASE_VA);
118     }
119     j++;
120     printf("(%x,%x) 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",
121                    udn_tile_coord_x(), udn_tile_coord_y(),
122            *((int *)(i)), *((int *)(i + 4)),
123            *((int *)(i + 4*2)), *((int *)(i + 4*3)),
124            *((int *)(i + 4*4)), *((int *)(i + 4*5)),
125            *((int *)(i + 4*6)), *((int *)(i + 4*7)),
126            *((int *)(i + 4*8)), *((int *)(i + 4*9)),
127            *((int *)(i + 4*10)), *((int *)(i + 4*11)),
128            *((int *)(i + 4*12)), *((int *)(i + 4*13)),
129            *((int *)(i + 4*14)), *((int *)(i + 4*15)));
130   }
131   printf("(%x,%x) \n", udn_tile_coord_x(), udn_tile_coord_y());
132 }
133 #endif
134
135 // should be invoked with interruption closed
136 inline void gc_enqueue_I(void *ptr) {
137 #ifdef DEBUG
138   BAMBOO_DEBUGPRINT(0xe601);
139   BAMBOO_DEBUGPRINT_REG(ptr);
140 #endif
141   if (gcheadindex==NUMPTRS) {
142     struct pointerblock * tmp;
143     if (gcspare!=NULL) {
144       tmp=gcspare;
145       gcspare=NULL;
146     } else {
147       tmp=RUNMALLOC_I(sizeof(struct pointerblock));
148     }             // if (gcspare!=NULL)
149     gchead->next=tmp;
150     gchead=tmp;
151     gcheadindex=0;
152   } // if (gcheadindex==NUMPTRS)
153   gchead->ptrs[gcheadindex++]=ptr;
154 #ifdef DEBUG
155   BAMBOO_DEBUGPRINT(0xe602);
156 #endif
157 } // void gc_enqueue_I(void *ptr)
158
159 // dequeue and destroy the queue
160 inline void * gc_dequeue_I() {
161   if (gctailindex==NUMPTRS) {
162     struct pointerblock *tmp=gctail;
163     gctail=gctail->next;
164     gctailindex=0;
165     if (gcspare!=NULL) {
166       RUNFREE(tmp);
167     } else {
168       gcspare=tmp;
169     }             // if (gcspare!=NULL)
170   } // if (gctailindex==NUMPTRS)
171   return gctail->ptrs[gctailindex++];
172 } // void * gc_dequeue()
173
174 // dequeue and do not destroy the queue
175 inline void * gc_dequeue2_I() {
176   if (gctailindex2==NUMPTRS) {
177     struct pointerblock *tmp=gctail2;
178     gctail2=gctail2->next;
179     gctailindex2=0;
180   } // if (gctailindex2==NUMPTRS)
181   return gctail2->ptrs[gctailindex2++];
182 } // void * gc_dequeue2()
183
184 inline int gc_moreItems_I() {
185   if ((gchead==gctail)&&(gctailindex==gcheadindex))
186     return 0;
187   return 1;
188 } // int gc_moreItems()
189
190 inline int gc_moreItems2_I() {
191   if ((gchead==gctail2)&&(gctailindex2==gcheadindex))
192     return 0;
193   return 1;
194 } // int gc_moreItems2()
195
196 // should be invoked with interruption closed
197 // enqueue a large obj: start addr & length
198 inline void gc_lobjenqueue_I(void *ptr,
199                              int length,
200                              int host) {
201 #ifdef DEBUG
202   BAMBOO_DEBUGPRINT(0xe901);
203 #endif
204   if (gclobjheadindex==NUMLOBJPTRS) {
205     struct lobjpointerblock * tmp;
206     if (gclobjspare!=NULL) {
207       tmp=gclobjspare;
208       gclobjspare=NULL;
209     } else {
210       tmp=RUNMALLOC_I(sizeof(struct lobjpointerblock));
211     }             // if (gclobjspare!=NULL)
212     gclobjhead->next=tmp;
213     tmp->prev = gclobjhead;
214     gclobjhead=tmp;
215     gclobjheadindex=0;
216   } // if (gclobjheadindex==NUMLOBJPTRS)
217   gclobjhead->lobjs[gclobjheadindex]=ptr;
218   gclobjhead->lengths[gclobjheadindex]=length;
219   gclobjhead->hosts[gclobjheadindex++]=host;
220 #ifdef DEBUG
221   BAMBOO_DEBUGPRINT_REG(gclobjhead->lobjs[gclobjheadindex-1]);
222   BAMBOO_DEBUGPRINT_REG(gclobjhead->lengths[gclobjheadindex-1]);
223   BAMBOO_DEBUGPRINT_REG(gclobjhead->hosts[gclobjheadindex-1]);
224 #endif
225 } // void gc_lobjenqueue_I(void *ptr...)
226
227 // dequeue and destroy the queue
228 inline void * gc_lobjdequeue_I(int * length,
229                                int * host) {
230   if (gclobjtailindex==NUMLOBJPTRS) {
231     struct lobjpointerblock *tmp=gclobjtail;
232     gclobjtail=gclobjtail->next;
233     gclobjtailindex=0;
234     gclobjtail->prev = NULL;
235     if (gclobjspare!=NULL) {
236       RUNFREE(tmp);
237     } else {
238       gclobjspare=tmp;
239       tmp->next = NULL;
240       tmp->prev = NULL;
241     }             // if (gclobjspare!=NULL)
242   } // if (gclobjtailindex==NUMLOBJPTRS)
243   if(length != NULL) {
244     *length = gclobjtail->lengths[gclobjtailindex];
245   }
246   if(host != NULL) {
247     *host = (int)(gclobjtail->hosts[gclobjtailindex]);
248   }
249   return gclobjtail->lobjs[gclobjtailindex++];
250 } // void * gc_lobjdequeue()
251
252 inline int gc_lobjmoreItems_I() {
253   if ((gclobjhead==gclobjtail)&&(gclobjtailindex==gclobjheadindex))
254     return 0;
255   return 1;
256 } // int gc_lobjmoreItems()
257
258 // dequeue and don't destroy the queue
259 inline void gc_lobjdequeue2_I() {
260   if (gclobjtailindex2==NUMLOBJPTRS) {
261     gclobjtail2=gclobjtail2->next;
262     gclobjtailindex2=1;
263   } else {
264     gclobjtailindex2++;
265   }      // if (gclobjtailindex2==NUMLOBJPTRS)
266 } // void * gc_lobjdequeue2()
267
268 inline int gc_lobjmoreItems2_I() {
269   if ((gclobjhead==gclobjtail2)&&(gclobjtailindex2==gclobjheadindex))
270     return 0;
271   return 1;
272 } // int gc_lobjmoreItems2()
273
274 // 'reversly' dequeue and don't destroy the queue
275 inline void gc_lobjdequeue3_I() {
276   if (gclobjtailindex2==0) {
277     gclobjtail2=gclobjtail2->prev;
278     gclobjtailindex2=NUMLOBJPTRS-1;
279   } else {
280     gclobjtailindex2--;
281   }      // if (gclobjtailindex2==NUMLOBJPTRS)
282 } // void * gc_lobjdequeue3()
283
284 inline int gc_lobjmoreItems3_I() {
285   if ((gclobjtail==gclobjtail2)&&(gclobjtailindex2==gclobjtailindex))
286     return 0;
287   return 1;
288 } // int gc_lobjmoreItems3()
289
290 inline void gc_lobjqueueinit4_I() {
291   gclobjtail2 = gclobjtail;
292   gclobjtailindex2 = gclobjtailindex;
293 } // void gc_lobjqueueinit2()
294
295 inline void * gc_lobjdequeue4_I(int * length,
296                                 int * host) {
297   if (gclobjtailindex2==NUMLOBJPTRS) {
298     gclobjtail2=gclobjtail2->next;
299     gclobjtailindex2=0;
300   } // if (gclobjtailindex==NUMLOBJPTRS)
301   if(length != NULL) {
302     *length = gclobjtail2->lengths[gclobjtailindex2];
303   }
304   if(host != NULL) {
305     *host = (int)(gclobjtail2->hosts[gclobjtailindex2]);
306   }
307   return gclobjtail2->lobjs[gclobjtailindex2++];
308 } // void * gc_lobjdequeue()
309
310 inline int gc_lobjmoreItems4_I() {
311   if ((gclobjhead==gclobjtail2)&&(gclobjtailindex2==gclobjheadindex))
312     return 0;
313   return 1;
314 } // int gc_lobjmoreItems(
315
316 INTPTR gccurr_heapbound = 0;
317
318 inline void gettype_size(void * ptr,
319                          int * ttype,
320                          int * tsize) {
321   int type = ((int *)ptr)[0];
322   int size = 0;
323   if(type < NUMCLASSES) {
324     // a normal object
325     size = classsize[type];
326   } else {
327     // an array
328     struct ArrayObject *ao=(struct ArrayObject *)ptr;
329     int elementsize=classsize[type];
330     int length=ao->___length___;
331     size=sizeof(struct ArrayObject)+length*elementsize;
332   }       // if(type < NUMCLASSES)
333   *ttype = type;
334   *tsize = size;
335 }
336
337 inline bool isLarge(void * ptr,
338                     int * ttype,
339                     int * tsize) {
340 #ifdef DEBUG
341   BAMBOO_DEBUGPRINT(0xe701);
342   BAMBOO_DEBUGPRINT_REG(ptr);
343 #endif
344   // check if a pointer is referring to a large object
345   gettype_size(ptr, ttype, tsize);
346 #ifdef DEBUG
347   BAMBOO_DEBUGPRINT(*tsize);
348 #endif
349   int bound = (BAMBOO_SMEM_SIZE);
350   if(((int)ptr-gcbaseva) < (BAMBOO_LARGE_SMEM_BOUND)) {
351     bound = (BAMBOO_SMEM_SIZE_L);
352   }
353   if((((int)ptr-gcbaseva)%(bound))==0) {
354     // ptr is a start of a block
355 #ifdef DEBUG
356     BAMBOO_DEBUGPRINT(0xe702);
357     BAMBOO_DEBUGPRINT(1);
358 #endif
359     return true;
360   }
361   if((bound-(((int)ptr-gcbaseva)%bound)) < (*tsize)) {
362     // it acrosses the boundary of current block
363 #ifdef DEBUG
364     BAMBOO_DEBUGPRINT(0xe703);
365     BAMBOO_DEBUGPRINT(1);
366 #endif
367     return true;
368   }
369 #ifdef DEBUG
370   BAMBOO_DEBUGPRINT(0);
371 #endif
372   return false;
373 } // bool isLarge(void * ptr, int * ttype, int * tsize)
374
375 inline int hostcore(void * ptr) {
376   // check the host core of ptr
377   int host = 0;
378   RESIDECORE(ptr, &host);
379 #ifdef DEBUG
380   BAMBOO_DEBUGPRINT(0xedd0);
381   BAMBOO_DEBUGPRINT_REG(ptr);
382   BAMBOO_DEBUGPRINT_REG(host);
383 #endif
384   return host;
385 } // int hostcore(void * ptr)
386
387 inline bool isLocal(void * ptr) {
388   // check if a pointer is in shared heap on this core
389   return hostcore(ptr) == BAMBOO_NUM_OF_CORE;
390 } // bool isLocal(void * ptr)
391
392 inline bool gc_checkCoreStatus_I() {
393   bool allStall = true;
394   for(int i = 0; i < NUMCORES4GC; ++i) {
395     if(gccorestatus[i] != 0) {
396       allStall = false;
397       break;
398     }             // if(gccorestatus[i] != 0)
399   }       // for(i = 0; i < NUMCORES4GC; ++i)
400   return allStall;
401 }
402
403 inline bool gc_checkAllCoreStatus_I() {
404   bool allStall = true;
405   for(int i = 0; i < NUMCORESACTIVE; ++i) {
406     if(gccorestatus[i] != 0) {
407       allStall = false;
408       break;
409     }             // if(gccorestatus[i] != 0)
410   }       // for(i = 0; i < NUMCORESACTIVE; ++i)
411   return allStall;
412 }
413
414 inline void checkMarkStatue() {
415 #ifdef DEBUG
416   BAMBOO_DEBUGPRINT(0xee01);
417 #endif
418   int i;
419   if((!waitconfirm) ||
420      (waitconfirm && (numconfirm == 0))) {
421 #ifdef DEBUG
422     BAMBOO_DEBUGPRINT(0xee02);
423 #endif
424     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
425     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
426     gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
427     gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
428     // check the status of all cores
429     bool allStall = gc_checkAllCoreStatus_I();
430 #ifdef DEBUG
431     BAMBOO_DEBUGPRINT(0xee03);
432 #endif
433     if(allStall) {
434 #ifdef DEBUG
435       BAMBOO_DEBUGPRINT(0xee04);
436 #endif
437       // ask for confirm
438       if(!waitconfirm) {
439 #ifdef DEBUG
440         BAMBOO_DEBUGPRINT(0xee05);
441 #endif
442         // the first time found all cores stall
443         // send out status confirm msg to all other cores
444         // reset the corestatus array too
445         gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
446         waitconfirm = true;
447         numconfirm = NUMCORESACTIVE - 1;
448         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
449         for(i = 1; i < NUMCORESACTIVE; ++i) {
450           gccorestatus[i] = 1;
451           // send mark phase finish confirm request msg to core i
452           send_msg_1(i, GCMARKCONFIRM, false);
453         }                         // for(i = 1; i < NUMCORESACTIVE; ++i)
454       } else {
455         // check if the sum of send objs and receive obj are the same
456         // yes->check if the info is the latest; no->go on executing
457         int sumsendobj = 0;
458         for(i = 0; i < NUMCORESACTIVE; ++i) {
459           sumsendobj += gcnumsendobjs[i];
460         }                         // for(i = 0; i < NUMCORESACTIVE; ++i)
461 #ifdef DEBUG
462         BAMBOO_DEBUGPRINT(0xee06);
463         BAMBOO_DEBUGPRINT_REG(sumsendobj);
464 #endif
465         for(i = 0; i < NUMCORESACTIVE; ++i) {
466           sumsendobj -= gcnumreceiveobjs[i];
467         }                         // for(i = 0; i < NUMCORESACTIVE; ++i)
468 #ifdef DEBUG
469         BAMBOO_DEBUGPRINT(0xee07);
470         BAMBOO_DEBUGPRINT_REG(sumsendobj);
471 #endif
472         if(0 == sumsendobj) {
473 #ifdef DEBUG
474           BAMBOO_DEBUGPRINT(0xee08);
475 #endif
476           // all the core status info are the latest
477           // stop mark phase
478           gcphase = COMPACTPHASE;
479           // restore the gcstatus for all cores
480           for(i = 0; i < NUMCORESACTIVE; ++i) {
481             gccorestatus[i] = 1;
482           }  // for(i = 0; i < NUMCORESACTIVE; ++i)
483         } else {
484           // wait for a while and ask for confirm again
485           int h = 100;
486           while(h--) {
487           }
488           waitconfirm = false;
489         }                        // if(0 == sumsendobj) else ...
490         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
491       }                   // if(!gcwaitconfirm) else()
492     } else {
493       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
494     }              // if(allStall)
495   }       // if((!waitconfirm)...
496 #ifdef DEBUG
497   BAMBOO_DEBUGPRINT(0xee0a);
498 #endif
499 } // void checkMarkStatue()
500
501 inline bool preGC() {
502   // preparation for gc
503   // make sure to clear all incoming msgs espacially transfer obj msgs
504 #ifdef DEBUG
505   BAMBOO_DEBUGPRINT(0xec01);
506 #endif
507   int i;
508   if((!waitconfirm) ||
509      (waitconfirm && (numconfirm == 0))) {
510     // send out status confirm msgs to all cores to check if there are
511     // transfer obj msgs on-the-fly
512     waitconfirm = true;
513     numconfirm = NUMCORESACTIVE - 1;
514     for(i = 1; i < NUMCORESACTIVE; ++i) {
515       corestatus[i] = 1;
516       // send status confirm msg to core i
517       send_msg_1(i, STATUSCONFIRM, false);
518     }             // for(i = 1; i < NUMCORESACTIVE; ++i)
519
520 #ifdef DEBUG
521     BAMBOO_DEBUGPRINT(0xec02);
522 #endif
523     while(true) {
524       if(numconfirm == 0) {
525         break;
526       }
527     }             // wait for confirmations
528     waitconfirm = false;
529     numconfirm = 0;
530 #ifdef DEBUG
531     BAMBOO_DEBUGPRINT(0xec03);
532 #endif
533     numsendobjs[BAMBOO_NUM_OF_CORE] = self_numsendobjs;
534     numreceiveobjs[BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
535     int sumsendobj = 0;
536 #ifdef DEBUG
537     BAMBOO_DEBUGPRINT(0xec04);
538 #endif
539     for(i = 0; i < NUMCORESACTIVE; ++i) {
540       sumsendobj += numsendobjs[i];
541 #ifdef DEBUG
542       BAMBOO_DEBUGPRINT(0xf000 + numsendobjs[i]);
543 #endif
544     }             // for(i = 1; i < NUMCORESACTIVE; ++i)
545 #ifdef DEBUG
546     BAMBOO_DEBUGPRINT(0xec05);
547     BAMBOO_DEBUGPRINT_REG(sumsendobj);
548 #endif
549     for(i = 0; i < NUMCORESACTIVE; ++i) {
550       sumsendobj -= numreceiveobjs[i];
551 #ifdef DEBUG
552       BAMBOO_DEBUGPRINT(0xf000 + numreceiveobjs[i]);
553 #endif
554     }             // for(i = 1; i < NUMCORESACTIVE; ++i)
555 #ifdef DEBUG
556     BAMBOO_DEBUGPRINT(0xec06);
557     BAMBOO_DEBUGPRINT_REG(sumsendobj);
558 #endif
559     if(0 == sumsendobj) {
560       return true;
561     } else {
562       // still have some transfer obj msgs on-the-fly, can not start gc
563       return false;
564     }             // if(0 == sumsendobj)
565   } else {
566 #ifdef DEBUG
567     BAMBOO_DEBUGPRINT(0xec07);
568 #endif
569     // previously asked for status confirmation and do not have all the
570     // confirmations yet, can not start gc
571     return false;
572   }       // if((!waitconfirm) ||
573 } // bool preGC()
574
575 inline void initGC() {
576   int i;
577   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
578     for(i = 0; i < NUMCORES4GC; ++i) {
579       gccorestatus[i] = 1;
580       gcnumsendobjs[i] = 0;
581       gcnumreceiveobjs[i] = 0;
582       gcloads[i] = 0;
583       gcrequiredmems[i] = 0;
584       gcfilledblocks[i] = 0;
585       gcstopblock[i] = 0;
586     } // for(i = 0; i < NUMCORES4GC; ++i)
587     for(i = NUMCORES4GC; i < NUMCORESACTIVE; ++i) {
588       gccorestatus[i] = 1;
589       gcnumsendobjs[i] = 0;
590       gcnumreceiveobjs[i] = 0;
591     }
592     gcheaptop = 0;
593     gctopcore = 0;
594     gctopblock = 0;
595   } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
596   gcself_numsendobjs = 0;
597   gcself_numreceiveobjs = 0;
598   gcmarkedptrbound = 0;
599   gcobj2map = 0;
600   gcmappedobj = 0;
601   //gcismapped = false;
602   gcnumlobjs = 0;
603   gcmovestartaddr = 0;
604   gctomove = false;
605   gcblock2fill = 0;
606   gcmovepending = 0;
607   gccurr_heaptop = 0;
608   gcdstcore = 0;
609
610   // initialize queue
611   if (gchead==NULL) {
612     gcheadindex=gctailindex=gctailindex2 = 0;
613     gchead=gctail=gctail2=RUNMALLOC(sizeof(struct pointerblock));
614   } else {
615     gctailindex = gctailindex2 = gcheadindex;
616     gctail = gctail2 = gchead;
617   }
618
619   // initialize the large obj queues
620   if (gclobjhead==NULL) {
621     gclobjheadindex=0;
622     gclobjtailindex=0;
623     gclobjtailindex2 = 0;
624     gclobjhead=gclobjtail=gclobjtail2=
625                              RUNMALLOC(sizeof(struct lobjpointerblock));
626   } else {
627     gclobjtailindex = gclobjtailindex2 = gclobjheadindex = 0;
628     gclobjtail = gclobjtail2 = gclobjhead;
629   }
630   gclobjhead->next = gclobjhead->prev = NULL;
631
632   freeRuntimeHash(gcpointertbl);
633   gcpointertbl = allocateRuntimeHash(20);
634   //gcpointertbl = allocateMGCHash(20);
635   //mgchashreset();
636
637   freeMGCHash(gcforwardobjtbl);
638   gcforwardobjtbl = allocateMGCHash(20, 3);
639
640   // initialize the mapping info related structures
641   if((BAMBOO_NUM_OF_CORE < NUMCORES4GC) && (gcsharedptbl != NULL)) {
642         // Never free the shared hash table, just reset it
643         /*freeGCSharedHash(gcsharedptbl);
644         gcsharedptbl = allocateGCSharedHash(20);*/
645         mgcsharedhashReset(gcsharedptbl);
646   }
647   // the shared hash tables are never changed 
648   //BAMBOO_MEMSET_WH(gcrpointertbls,0,sizeof(struct RuntimeHash *)*NUMCORES4GC);
649 #ifdef GC_PROFILE
650   // TODO
651   num_mapinforequest = 0;
652   num_mapinforequest_i = 0;
653   flushstalltime = 0;
654   flushstalltime_i = 0;
655   num_markrequest = 0;
656   marktime = 0;
657 #endif
658 } // void initGC()
659
660 // compute load balance for all cores
661 inline int loadbalance(int * heaptop) {
662   // compute load balance
663   int i;
664
665   // get the total loads
666   int tloads = gcloads[STARTUPCORE];
667   for(i = 1; i < NUMCORES4GC; i++) {
668     tloads += gcloads[i];
669   }
670   *heaptop = gcbaseva + tloads;
671 #ifdef DEBUG
672   BAMBOO_DEBUGPRINT(0xdddd);
673   BAMBOO_DEBUGPRINT_REG(tloads);
674   BAMBOO_DEBUGPRINT_REG(*heaptop);
675 #endif
676   int b = 0;
677   BLOCKINDEX(*heaptop, &b);
678   int numbpc = b / NUMCORES4GC;       // num of blocks per core
679 #ifdef DEBUG
680   BAMBOO_DEBUGPRINT_REG(b);
681   BAMBOO_DEBUGPRINT_REG(numbpc);
682 #endif
683   gctopblock = b;
684   RESIDECORE(heaptop, &gctopcore);
685 #ifdef DEBUG
686   BAMBOO_DEBUGPRINT_REG(gctopcore);
687 #endif
688   return numbpc;
689 } // void loadbalance(int * heaptop)
690
691 inline bool cacheLObjs() {
692   // check the total mem size need for large objs
693   int sumsize = 0;
694   int size = 0;
695 #ifdef DEBUG
696   BAMBOO_DEBUGPRINT(0xe801);
697 #endif
698   gclobjtail2 = gclobjtail;
699   gclobjtailindex2 = gclobjtailindex;
700   int tmp_lobj = 0;
701   int tmp_len = 0;
702   int tmp_host = 0;
703   // compute total mem size required and sort the lobjs in ascending order
704   while(gc_lobjmoreItems2_I()) {
705     gc_lobjdequeue2_I();
706     tmp_lobj = gclobjtail2->lobjs[gclobjtailindex2-1];
707     tmp_host = gclobjtail2->hosts[gclobjtailindex2-1];
708     tmp_len = gclobjtail2->lengths[gclobjtailindex2 - 1];
709     sumsize += tmp_len;
710 #ifdef DEBUG
711     BAMBOO_DEBUGPRINT_REG(gclobjtail2->lobjs[gclobjtailindex2-1]);
712     BAMBOO_DEBUGPRINT_REG(tmp_len);
713     BAMBOO_DEBUGPRINT_REG(sumsize);
714 #endif
715     int i = gclobjtailindex2-1;
716     struct lobjpointerblock * tmp_block = gclobjtail2;
717     // find the place to insert
718     while(true) {
719       if(i == 0) {
720         if(tmp_block->prev == NULL) {
721           break;
722         }
723         if(tmp_block->prev->lobjs[NUMLOBJPTRS-1] > tmp_lobj) {
724           tmp_block->lobjs[i] = tmp_block->prev->lobjs[NUMLOBJPTRS-1];
725           tmp_block->lengths[i] = tmp_block->prev->lengths[NUMLOBJPTRS-1];
726           tmp_block->hosts[i] = tmp_block->prev->hosts[NUMLOBJPTRS-1];
727           tmp_block = tmp_block->prev;
728           i = NUMLOBJPTRS-1;
729         } else {
730           break;
731         }                         // if(tmp_block->prev->lobjs[NUMLOBJPTRS-1] < tmp_lobj)
732       } else {
733         if(tmp_block->lobjs[i-1] > tmp_lobj) {
734           tmp_block->lobjs[i] = tmp_block->lobjs[i-1];
735           tmp_block->lengths[i] = tmp_block->lengths[i-1];
736           tmp_block->hosts[i] = tmp_block->hosts[i-1];
737           i--;
738         } else {
739           break;
740         }                         // if(tmp_block->lobjs[i-1] < tmp_lobj)
741       }                   // if(i ==0 ) else {}
742     }             // while(true)
743                   // insert it
744     if(i != gclobjtailindex2 - 1) {
745       tmp_block->lobjs[i] = tmp_lobj;
746       tmp_block->lengths[i] = tmp_len;
747       tmp_block->hosts[i] = tmp_host;
748     }
749   }       // while(gc_lobjmoreItems2())
750
751   // check if there are enough space to cache these large objs
752   INTPTR dst = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE) -sumsize;
753   if(gcheaptop > dst) {
754     // do not have enough room to cache large objs
755 #ifdef DEBUG
756     BAMBOO_DEBUGPRINT(0xe802);
757     BAMBOO_DEBUGPRINT_REG(dst);
758     BAMBOO_DEBUGPRINT_REG(gcheaptop);
759 #endif
760     return false;
761   }
762 #ifdef DEBUG
763   BAMBOO_DEBUGPRINT(0xe803);
764   BAMBOO_DEBUGPRINT_REG(dst);
765   BAMBOO_DEBUGPRINT_REG(gcheaptop);
766 #endif
767
768   gcheaptop = dst; // Note: record the start of cached lobjs with gcheaptop
769   // cache the largeObjs to the top of the shared heap
770   //gclobjtail2 = gclobjtail;
771   //gclobjtailindex2 = gclobjtailindex;
772   dst = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE);
773   while(gc_lobjmoreItems3_I()) {
774     gc_lobjdequeue3_I();
775     size = gclobjtail2->lengths[gclobjtailindex2];
776     // set the mark field to , indicating that this obj has been moved
777     // and need to be flushed
778     ((int *)(gclobjtail2->lobjs[gclobjtailindex2]))[6] = COMPACTED;
779     dst -= size;
780     if((int)dst < (int)(gclobjtail2->lobjs[gclobjtailindex2])+size) {
781       memmove(dst, gclobjtail2->lobjs[gclobjtailindex2], size);
782     } else {
783       //BAMBOO_WRITE_HINT_CACHE(dst, size);
784       memcpy(dst, gclobjtail2->lobjs[gclobjtailindex2], size);
785     }
786 #ifdef DEBUG
787     BAMBOO_DEBUGPRINT(0x804);
788     BAMBOO_DEBUGPRINT_REG(gclobjtail2->lobjs[gclobjtailindex2]);
789     BAMBOO_DEBUGPRINT(dst);
790     BAMBOO_DEBUGPRINT_REG(size);
791     BAMBOO_DEBUGPRINT_REG(*((int*)gclobjtail2->lobjs[gclobjtailindex2]));
792     BAMBOO_DEBUGPRINT_REG(*((int*)(dst)));
793 #endif
794   }
795   return true;
796 } // void cacheLObjs()
797
798 // NOTE: the free mem chunks should be maintained in an ordered linklist
799 // the listtop param always specify current list tail
800
801 // update the bmmboo_smemtbl to record current shared mem usage
802 void updateSmemTbl(int coren,
803                    int localtop) {
804   int ltopcore = 0;
805   int bound = BAMBOO_SMEM_SIZE_L;
806   BLOCKINDEX(localtop, &ltopcore);
807   if(localtop >= (gcbaseva+(BAMBOO_LARGE_SMEM_BOUND))) {
808     bound = BAMBOO_SMEM_SIZE;
809   }
810   int load = (localtop-gcbaseva)%bound;
811   int i = 0;
812   int j = 0;
813   int toset = 0;
814   do {
815     toset = gc_core2block[2*coren+i]+(NUMCORES4GC*2)*j;
816     if(toset < ltopcore) {
817       bamboo_smemtbl[toset]=
818         (toset<NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
819     } else if(toset == ltopcore) {
820       bamboo_smemtbl[toset] = load;
821       break;
822     } else {
823       break;
824     }
825     i++;
826     if(i == 2) {
827       i = 0;
828       j++;
829     }
830   } while(true);
831 } // void updateSmemTbl(int, int)
832
833 inline void moveLObjs() {
834 #ifdef DEBUG
835   BAMBOO_DEBUGPRINT(0xea01);
836 #endif
837   // zero out the smemtbl
838   BAMBOO_MEMSET_WH(bamboo_smemtbl, 0, sizeof(int)*gcnumblock);
839   // find current heap top
840   // flush all gcloads to indicate the real heap top on one core
841   // previous it represents the next available ptr on a core
842   if((gcloads[0] > (gcbaseva+(BAMBOO_SMEM_SIZE_L)))
843      && ((gcloads[0]%(BAMBOO_SMEM_SIZE)) == 0)) {
844     // edge of a block, check if this is exactly the heaptop
845     BASEPTR(0, gcfilledblocks[0]-1, &(gcloads[0]));
846     gcloads[0]+=(gcfilledblocks[0]>1 ?
847                  (BAMBOO_SMEM_SIZE) : (BAMBOO_SMEM_SIZE_L));
848   }
849   updateSmemTbl(0, gcloads[0]);
850 #ifdef DEBUG
851   BAMBOO_DEBUGPRINT(0xea02);
852   BAMBOO_DEBUGPRINT_REG(gcloads[0]);
853   BAMBOO_DEBUGPRINT_REG(bamboo_smemtbl[0]);
854 #endif
855   for(int i = 1; i < NUMCORES4GC; i++) {
856     int tmptop = 0;
857 #ifdef DEBUG
858     BAMBOO_DEBUGPRINT(0xf000+i);
859     BAMBOO_DEBUGPRINT_REG(gcloads[i]);
860     BAMBOO_DEBUGPRINT_REG(gcfilledblocks[i]);
861 #endif
862     if((gcfilledblocks[i] > 0)
863        && ((gcloads[i] % (BAMBOO_SMEM_SIZE)) == 0)) {
864       // edge of a block, check if this is exactly the heaptop
865       BASEPTR(i, gcfilledblocks[i]-1, &gcloads[i]);
866       gcloads[i]
867         +=(gcfilledblocks[i]>1 ? (BAMBOO_SMEM_SIZE) : (BAMBOO_SMEM_SIZE_L));
868       tmptop = gcloads[i];
869     }
870     updateSmemTbl(i, gcloads[i]);
871 #ifdef DEBUG
872     BAMBOO_DEBUGPRINT_REG(gcloads[i]);
873 #endif
874   }       // for(int i = 1; i < NUMCORES4GC; i++) {
875
876   // find current heap top
877   // TODO
878   // a bug here: when using local allocation, directly move large objects
879   // to the highest free chunk might not be memory efficient
880   int tmpheaptop = 0;
881   int size = 0;
882   int bound = 0;
883   int i = 0;
884   for(i = gcnumblock-1; i >= 0; i--) {
885     if(bamboo_smemtbl[i] > 0) {
886       break;
887     }
888   }
889   if(i == -1) {
890     tmpheaptop = gcbaseva;
891   } else {
892     tmpheaptop = gcbaseva+bamboo_smemtbl[i]+((i<NUMCORES4GC) ?
893                 (BAMBOO_SMEM_SIZE_L*i) :
894         (BAMBOO_SMEM_SIZE*(i-NUMCORES4GC)+BAMBOO_LARGE_SMEM_BOUND));
895   }
896
897   // move large objs from gcheaptop to tmpheaptop
898   // write the header first
899   int tomove = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE) -gcheaptop;
900 #ifdef DEBUG
901   BAMBOO_DEBUGPRINT(0xea03);
902   BAMBOO_DEBUGPRINT_REG(tomove);
903   BAMBOO_DEBUGPRINT_REG(tmpheaptop);
904   BAMBOO_DEBUGPRINT_REG(gcheaptop);
905 #endif
906   // flush the sbstartbl
907   BAMBOO_MEMSET_WH(&(gcsbstarttbl[gcreservedsb]), '\0',
908                    (BAMBOO_SHARED_MEM_SIZE/BAMBOO_SMEM_SIZE-gcreservedsb)*sizeof(INTPTR));
909   if(tomove == 0) {
910     gcheaptop = tmpheaptop;
911   } else {
912     // check how many blocks it acrosses
913     int remain = tmpheaptop-gcbaseva;
914     int sb = remain/(BAMBOO_SMEM_SIZE) + gcreservedsb;             //number of the sblock
915     int b = 0;             // number of the block
916     BLOCKINDEX(tmpheaptop, &b);
917     // check the remaining space in this block
918     bound = (BAMBOO_SMEM_SIZE);
919     if(remain < (BAMBOO_LARGE_SMEM_BOUND)) {
920       bound = (BAMBOO_SMEM_SIZE_L);
921     }
922     remain = bound - remain%bound;
923
924 #ifdef DEBUG
925     BAMBOO_DEBUGPRINT(0xea04);
926 #endif
927     size = 0;
928     int isize = 0;
929     int host = 0;
930     int ptr = 0;
931     int base = tmpheaptop;
932     int cpysize = 0;
933     remain -= BAMBOO_CACHE_LINE_SIZE;
934     tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
935     gc_lobjqueueinit4_I();
936     while(gc_lobjmoreItems4_I()) {
937       ptr = (int)(gc_lobjdequeue4_I(&size, &host));
938       ALIGNSIZE(size, &isize);
939       if(remain < isize) {
940         // this object acrosses blocks
941         if(cpysize > 0) {
942           // close current block, fill its header
943           BAMBOO_MEMSET_WH(base, '\0', BAMBOO_CACHE_LINE_SIZE);
944           *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
945           bamboo_smemtbl[b]+=BAMBOO_CACHE_LINE_SIZE;                               // add the size of the header
946           cpysize = 0;
947           base = tmpheaptop;
948           if(remain == 0) {
949             remain = ((tmpheaptop-gcbaseva)<(BAMBOO_LARGE_SMEM_BOUND)) ?
950                      BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
951           }
952           remain -= BAMBOO_CACHE_LINE_SIZE;
953           tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
954           BLOCKINDEX(tmpheaptop, &b);
955           sb = (tmpheaptop-gcbaseva)/(BAMBOO_SMEM_SIZE) + gcreservedsb;
956         }                         // if(cpysize > 0)
957
958         // move the large obj
959         if((int)gcheaptop < (int)(tmpheaptop)+size) {
960           memmove(tmpheaptop, gcheaptop, size);
961         } else {
962           //BAMBOO_WRITE_HINT_CACHE(tmpheaptop, size);
963           memcpy(tmpheaptop, gcheaptop, size);
964         }
965         // fill the remaining space with -2 padding
966         BAMBOO_MEMSET_WH(tmpheaptop+size, -2, isize-size);
967         // zero out original mem caching the lobj
968         BAMBOO_MEMSET_WH(gcheaptop, '\0', size);
969 #ifdef DEBUG
970         BAMBOO_DEBUGPRINT(0xea05);
971         BAMBOO_DEBUGPRINT_REG(gcheaptop);
972         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
973         BAMBOO_DEBUGPRINT_REG(size);
974         BAMBOO_DEBUGPRINT_REG(isize);
975         BAMBOO_DEBUGPRINT_REG(base);
976 #endif
977         gcheaptop += size;
978         // cache the mapping info anyway
979         //if(ptr != tmpheaptop) {
980         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
981         //mgchashInsert_I(ptr, tmpheaptop);
982         RuntimeHashadd_I(gcpointertbl, ptr, tmpheaptop);
983         //struct nodemappinginfo * nodeinfo = NULL;
984         //RuntimeHashget(gcpointertbl, ptr, &nodeinfo);
985         //nodeinfo->ptr = tmpheaptop;
986         //MGCHashadd_I(gcpointertbl, ptr, tmpheaptop);
987         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
988         //}
989 #ifdef DEBUG
990         BAMBOO_DEBUGPRINT(0xcdca);
991         BAMBOO_DEBUGPRINT_REG(ptr);
992         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
993 #endif
994         if(host != BAMBOO_NUM_OF_CORE) {
995           // send the original host core with the mapping info
996           send_msg_3(host, GCLOBJMAPPING, ptr, tmpheaptop, false);
997 #ifdef DEBUG
998           BAMBOO_DEBUGPRINT(0xcdcb);
999           BAMBOO_DEBUGPRINT_REG(ptr);
1000           BAMBOO_DEBUGPRINT_REG(tmpheaptop);
1001 #endif
1002         }                         // if(host != BAMBOO_NUM_OF_CORE)
1003         tmpheaptop += isize;
1004
1005         // set the gcsbstarttbl and bamboo_smemtbl
1006         int tmpsbs = 1+(isize-remain-1)/BAMBOO_SMEM_SIZE;
1007         for(int k = 1; k < tmpsbs; k++) {
1008           gcsbstarttbl[sb+k] = (INTPTR)(-1);
1009         }
1010         sb += tmpsbs;
1011         bound = (b<NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1012         BLOCKINDEX(tmpheaptop-1, &tmpsbs);
1013         for(; b < tmpsbs; b++) {
1014           bamboo_smemtbl[b] = bound;
1015           if(b==NUMCORES4GC-1) {
1016             bound = BAMBOO_SMEM_SIZE;
1017           }
1018         }
1019         if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) {
1020           gcsbstarttbl[sb] = (INTPTR)(-1);
1021           remain = ((tmpheaptop-gcbaseva)<(BAMBOO_LARGE_SMEM_BOUND)) ?
1022                    BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1023           bamboo_smemtbl[b] = bound;
1024         } else {
1025           gcsbstarttbl[sb] = (INTPTR)(tmpheaptop);
1026           remain = tmpheaptop-gcbaseva;
1027           bamboo_smemtbl[b] = remain%bound;
1028           remain = bound - bamboo_smemtbl[b];
1029         }                         // if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) else ...
1030
1031         // close current block and fill the header
1032         BAMBOO_MEMSET_WH(base, '\0', BAMBOO_CACHE_LINE_SIZE);
1033         *((int*)base) = isize + BAMBOO_CACHE_LINE_SIZE;
1034         cpysize = 0;
1035         base = tmpheaptop;
1036         if(remain == BAMBOO_CACHE_LINE_SIZE) {
1037           // fill with 0 in case
1038           BAMBOO_MEMSET_WH(tmpheaptop, '\0', remain);
1039         }
1040         remain -= BAMBOO_CACHE_LINE_SIZE;
1041         tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
1042       } else {
1043         remain -= isize;
1044         // move the large obj
1045         if((int)gcheaptop < (int)(tmpheaptop)+size) {
1046           memmove(tmpheaptop, gcheaptop, size);
1047         } else {
1048           //BAMBOO_WRITE_HINT_CACHE(tmpheaptop, size);
1049           memcpy(tmpheaptop, gcheaptop, size);
1050         }
1051         // fill the remaining space with -2 padding
1052         BAMBOO_MEMSET_WH(tmpheaptop+size, -2, isize-size);
1053         // zero out original mem caching the lobj
1054         BAMBOO_MEMSET_WH(gcheaptop, '\0', size);
1055 #ifdef DEBUG
1056         BAMBOO_DEBUGPRINT(0xea06);
1057         BAMBOO_DEBUGPRINT_REG(gcheaptop);
1058         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
1059         BAMBOO_DEBUGPRINT_REG(size);
1060         BAMBOO_DEBUGPRINT_REG(isize);
1061 #endif
1062
1063         gcheaptop += size;
1064         cpysize += isize;
1065         // cache the mapping info anyway
1066         //if(ptr != tmpheaptop) {
1067         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1068         //mgchashInsert_I(ptr, tmpheaptop);
1069         RuntimeHashadd_I(gcpointertbl, ptr, tmpheaptop);
1070         //struct nodemappinginfo * nodeinfo = NULL;
1071         //RuntimeHashget(gcpointertbl, ptr, &nodeinfo);
1072         //nodeinfo->ptr = tmpheaptop;
1073         //MGCHashadd_I(gcpointertbl, ptr, tmpheaptop);
1074         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1075         //}
1076 #ifdef DEBUG
1077         BAMBOO_DEBUGPRINT(0xcdcc);
1078         BAMBOO_DEBUGPRINT_REG(ptr);
1079         BAMBOO_DEBUGPRINT_REG(tmpheaptop);
1080         BAMBOO_DEBUGPRINT_REG(*((int*)tmpheaptop));
1081 #endif
1082         if(host != BAMBOO_NUM_OF_CORE) {
1083           // send the original host core with the mapping info
1084           send_msg_3(host, GCLOBJMAPPING, ptr, tmpheaptop, false);
1085 #ifdef DEBUG
1086           BAMBOO_DEBUGPRINT(0xcdcd);
1087           BAMBOO_DEBUGPRINT_REG(ptr);
1088           BAMBOO_DEBUGPRINT_REG(tmpheaptop);
1089 #endif
1090         }                         // if(host != BAMBOO_NUM_OF_CORE)
1091         tmpheaptop += isize;
1092
1093         // update bamboo_smemtbl
1094         bamboo_smemtbl[b] += isize;
1095       }                   // if(remain < isize) else ...
1096     }             // while(gc_lobjmoreItems())
1097     if(cpysize > 0) {
1098       // close current block, fill the header
1099       BAMBOO_MEMSET_WH(base, '\0', BAMBOO_CACHE_LINE_SIZE);
1100       *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
1101       bamboo_smemtbl[b] += BAMBOO_CACHE_LINE_SIZE;                   // add the size of the header
1102     } else {
1103       tmpheaptop -= BAMBOO_CACHE_LINE_SIZE;
1104     }
1105     gcheaptop = tmpheaptop;
1106
1107   }       // if(tomove == 0)
1108
1109 #ifdef DEBUG
1110   BAMBOO_DEBUGPRINT(0xea07);
1111   BAMBOO_DEBUGPRINT_REG(gcheaptop);
1112 #endif
1113
1114   bamboo_free_block = 0;
1115   int tbound = 0;
1116   do {
1117     tbound = (bamboo_free_block<NUMCORES4GC) ?
1118              BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1119     if(bamboo_smemtbl[bamboo_free_block] == tbound) {
1120       bamboo_free_block++;
1121     } else {
1122       // the first non-full partition
1123       break;
1124     }
1125   } while(true);
1126 #ifdef DEBUG
1127   BAMBOO_DEBUGPRINT(0xea08);
1128   BAMBOO_DEBUGPRINT_REG(gcheaptop);
1129 #endif
1130 } // void moveLObjs()
1131
1132 inline void markObj(void * objptr) {
1133   if(objptr == NULL) {
1134     return;
1135   }
1136   if(ISSHAREDOBJ(objptr)) {
1137     int host = hostcore(objptr);
1138     if(BAMBOO_NUM_OF_CORE == host) {
1139       // on this core
1140       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1141       if(((int *)objptr)[6] == INIT) {
1142         // this is the first time that this object is discovered,
1143         // set the flag as DISCOVERED
1144         ((int *)objptr)[6] |= DISCOVERED;
1145         gc_enqueue_I(objptr);
1146           }
1147       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1148     } else {
1149 #ifdef DEBUG
1150       BAMBOO_DEBUGPRINT(0xbbbb);
1151       BAMBOO_DEBUGPRINT_REG(host);
1152       BAMBOO_DEBUGPRINT_REG(objptr);
1153 #endif
1154       // check if this obj has been forwarded
1155       if(!MGCHashcontains(gcforwardobjtbl, (int)objptr)) {
1156 #ifdef GC_PROFILE
1157         // TODO unsigned long long ttime = BAMBOO_GET_EXE_TIME();
1158 #endif
1159         // send a msg to host informing that objptr is active
1160         send_msg_2(host, GCMARKEDOBJ, objptr, /*BAMBOO_NUM_OF_CORE,*/ false);
1161 #ifdef GC_PROFILE
1162         // TODO
1163         /*
1164         marktime += BAMBOO_GET_EXE_TIME() - ttime;
1165         num_markrequest++;*/
1166 #endif
1167         gcself_numsendobjs++;
1168         MGCHashadd(gcforwardobjtbl, (int)objptr);
1169       }
1170     }
1171   } else {
1172     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1173     gc_enqueue_I(objptr);
1174     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1175   }       // if(ISSHAREDOBJ(objptr))
1176 } // void markObj(void * objptr)
1177
1178 // enqueue root objs
1179 inline void tomark(struct garbagelist * stackptr) {
1180   if(MARKPHASE != gcphase) {
1181 #ifdef DEBUG
1182     BAMBOO_DEBUGPRINT_REG(gcphase);
1183 #endif
1184     BAMBOO_EXIT(0xb101);
1185   }
1186   gcbusystatus = true;
1187   gcnumlobjs = 0;
1188
1189   int i,j;
1190   // enqueue current stack
1191   while(stackptr!=NULL) {
1192 #ifdef DEBUG
1193     BAMBOO_DEBUGPRINT(0xe501);
1194     BAMBOO_DEBUGPRINT_REG(stackptr->size);
1195     BAMBOO_DEBUGPRINT_REG(stackptr->next);
1196     BAMBOO_DEBUGPRINT_REG(stackptr->array[0]);
1197 #endif
1198     for(i=0; i<stackptr->size; i++) {
1199       if(stackptr->array[i] != NULL) {
1200         markObj(stackptr->array[i]);
1201       }
1202     }
1203     stackptr=stackptr->next;
1204   }
1205
1206 #ifdef DEBUG
1207   BAMBOO_DEBUGPRINT(0xe503);
1208 #endif
1209   // enqueue objectsets
1210   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
1211     for(i=0; i<NUMCLASSES; i++) {
1212       struct parameterwrapper ** queues =
1213         objectqueues[BAMBOO_NUM_OF_CORE][i];
1214       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
1215       for(j = 0; j < length; ++j) {
1216         struct parameterwrapper * parameter = queues[j];
1217         struct ObjectHash * set=parameter->objectset;
1218         struct ObjectNode * ptr=set->listhead;
1219         while(ptr!=NULL) {
1220           markObj((void *)ptr->key);
1221           ptr=ptr->lnext;
1222         }
1223       }
1224     }
1225   }
1226
1227   // euqueue current task descriptor
1228   if(currtpd != NULL) {
1229 #ifdef DEBUG
1230     BAMBOO_DEBUGPRINT(0xe504);
1231 #endif
1232     for(i=0; i<currtpd->numParameters; i++) {
1233       markObj(currtpd->parameterArray[i]);
1234     }
1235   }
1236
1237 #ifdef DEBUG
1238   BAMBOO_DEBUGPRINT(0xe505);
1239 #endif
1240   // euqueue active tasks
1241   if(activetasks != NULL) {
1242     struct genpointerlist * ptr=activetasks->list;
1243     while(ptr!=NULL) {
1244       struct taskparamdescriptor *tpd=ptr->src;
1245       int i;
1246       for(i=0; i<tpd->numParameters; i++) {
1247         markObj(tpd->parameterArray[i]);
1248       }
1249       ptr=ptr->inext;
1250     }
1251   }
1252
1253 #ifdef DEBUG
1254   BAMBOO_DEBUGPRINT(0xe506);
1255 #endif
1256   // enqueue cached transferred obj
1257   struct QueueItem * tmpobjptr =  getHead(&objqueue);
1258   while(tmpobjptr != NULL) {
1259     struct transObjInfo * objInfo =
1260       (struct transObjInfo *)(tmpobjptr->objectptr);
1261     markObj(objInfo->objptr);
1262     tmpobjptr = getNextQueueItem(tmpobjptr);
1263   }
1264
1265 #ifdef DEBUG
1266   BAMBOO_DEBUGPRINT(0xe507);
1267 #endif
1268   // enqueue cached objs to be transferred
1269   struct QueueItem * item = getHead(totransobjqueue);
1270   while(item != NULL) {
1271     struct transObjInfo * totransobj =
1272       (struct transObjInfo *)(item->objectptr);
1273     markObj(totransobj->objptr);
1274     item = getNextQueueItem(item);
1275   }       // while(item != NULL)
1276
1277 #ifdef DEBUG
1278   BAMBOO_DEBUGPRINT(0xe508);
1279 #endif
1280   // enqueue lock related info
1281   for(i = 0; i < runtime_locklen; ++i) {
1282     markObj((void *)(runtime_locks[i].redirectlock));
1283     if(runtime_locks[i].value != NULL) {
1284       markObj((void *)(runtime_locks[i].value));
1285     }
1286   }
1287
1288 } // void tomark(struct garbagelist * stackptr)
1289
1290 inline void mark(bool isfirst,
1291                  struct garbagelist * stackptr) {
1292 #ifdef DEBUG
1293   if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT(0xed01);
1294 #endif
1295   if(isfirst) {
1296 #ifdef DEBUG
1297     if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT(0xed02);
1298 #endif
1299     // enqueue root objs
1300     tomark(stackptr);
1301     gccurr_heaptop = 0; // record the size of all active objs in this core
1302                         // aligned but does not consider block boundaries
1303     gcmarkedptrbound = 0;
1304   }
1305 #ifdef DEBUG
1306   if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT(0xed03);
1307 #endif
1308   int isize = 0;
1309   bool checkfield = true;
1310   bool sendStall = false;
1311   // mark phase
1312   while(MARKPHASE == gcphase) {
1313 #ifdef DEBUG
1314     if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT(0xed04);
1315 #endif
1316     while(true) {
1317       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1318       bool hasItems = gc_moreItems2_I();
1319       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1320 #ifdef DEBUG
1321       BAMBOO_DEBUGPRINT(0xed05);
1322 #endif
1323       if(!hasItems) {
1324         break;
1325       }
1326       sendStall = false;
1327       gcbusystatus = true;
1328       checkfield = true;
1329       void * ptr = gc_dequeue2_I();
1330
1331 #ifdef DEBUG
1332       BAMBOO_DEBUGPRINT_REG(ptr);
1333 #endif
1334       int size = 0;
1335       int isize = 0;
1336       int type = 0;
1337       // check if it is a shared obj
1338       if(ISSHAREDOBJ(ptr)) {
1339         // a shared obj, check if it is a local obj on this core
1340         int host = hostcore(ptr);
1341         bool islocal = (host == BAMBOO_NUM_OF_CORE);
1342         if(islocal) {
1343           bool isnotmarked = ((((int *)ptr)[6] & DISCOVERED) != 0);
1344           if(isLarge(ptr, &type, &size) && isnotmarked) {
1345             // ptr is a large object and not marked or enqueued
1346 #ifdef DEBUG
1347             BAMBOO_DEBUGPRINT(0xecec);
1348             BAMBOO_DEBUGPRINT_REG(ptr);
1349             BAMBOO_DEBUGPRINT_REG(*((int*)ptr));
1350 #endif
1351             BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1352             gc_lobjenqueue_I(ptr, size, BAMBOO_NUM_OF_CORE);
1353             gcnumlobjs++;
1354             BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1355             // mark this obj
1356             ((int *)ptr)[6] = ((int *)ptr)[6] & (~DISCOVERED) | MARKED;
1357           } else if(isnotmarked) {
1358             // ptr is an unmarked active object on this core
1359             ALIGNSIZE(size, &isize);
1360             gccurr_heaptop += isize;
1361 #ifdef DEBUG
1362             BAMBOO_DEBUGPRINT(0xaaaa);
1363             BAMBOO_DEBUGPRINT_REG(ptr);
1364             BAMBOO_DEBUGPRINT_REG(isize);
1365             BAMBOO_DEBUGPRINT(((int *)(ptr))[0]);
1366 #endif
1367             // mark this obj
1368             ((int *)ptr)[6] = ((int *)ptr)[6] & (~DISCOVERED) | MARKED;
1369           
1370                 if(ptr + size > gcmarkedptrbound) {
1371               gcmarkedptrbound = ptr + size;
1372             } // if(ptr + size > gcmarkedptrbound)
1373           } else {
1374             // ptr is not an active obj or has been marked
1375             checkfield = false;
1376           } // if(isLarge(ptr, &type, &size)) else ...
1377         }  /* can never reach here
1378     else {
1379 #ifdef DEBUG
1380           if(BAMBOO_NUM_OF_CORE == 0) {
1381         BAMBOO_DEBUGPRINT(0xbbbb);
1382         BAMBOO_DEBUGPRINT_REG(host);
1383         BAMBOO_DEBUGPRINT_REG(ptr);
1384       }
1385 #endif
1386       // check if this obj has been forwarded
1387       if(!MGCHashcontains(gcforwardobjtbl, (int)ptr)) {
1388         // send a msg to host informing that ptr is active
1389                 send_msg_2(host, GCMARKEDOBJ, ptr, false);
1390                 gcself_numsendobjs++;
1391                 MGCHashadd(gcforwardobjtbl, (int)ptr);
1392           }
1393             checkfield = false;
1394         }// if(isLocal(ptr)) else ...*/
1395       }                   // if(ISSHAREDOBJ(ptr))
1396 #ifdef DEBUG
1397       BAMBOO_DEBUGPRINT(0xed06);
1398 #endif
1399
1400       if(checkfield) {
1401         // scan all pointers in ptr
1402         unsigned INTPTR * pointer;
1403         pointer=pointerarray[type];
1404         if (pointer==0) {
1405           /* Array of primitives */
1406           /* Do nothing */
1407         } else if (((INTPTR)pointer)==1) {
1408           /* Array of pointers */
1409           struct ArrayObject *ao=(struct ArrayObject *) ptr;
1410           int length=ao->___length___;
1411           int j;
1412           for(j=0; j<length; j++) {
1413             void *objptr =
1414               ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
1415             markObj(objptr);
1416           }
1417         } else {
1418           INTPTR size=pointer[0];
1419           int i;
1420           for(i=1; i<=size; i++) {
1421             unsigned int offset=pointer[i];
1422             void * objptr=*((void **)(((char *)ptr)+offset));
1423             markObj(objptr);
1424           }
1425         }     // if (pointer==0) else if ... else ...
1426       }   // if(checkfield)
1427     }     // while(gc_moreItems2())
1428 #ifdef DEBUG
1429     BAMBOO_DEBUGPRINT(0xed07);
1430 #endif
1431     gcbusystatus = false;
1432     // send mark finish msg to core coordinator
1433     if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1434 #ifdef DEBUG
1435       BAMBOO_DEBUGPRINT(0xed08);
1436 #endif
1437       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1438       gcnumsendobjs[BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
1439       gcnumreceiveobjs[BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
1440       gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
1441     } else {
1442       if(!sendStall) {
1443 #ifdef DEBUG
1444         BAMBOO_DEBUGPRINT(0xed09);
1445 #endif
1446         send_msg_4(STARTUPCORE, GCFINISHMARK, BAMBOO_NUM_OF_CORE,
1447                    gcself_numsendobjs, gcself_numreceiveobjs, false);
1448         sendStall = true;
1449       }
1450     }             // if(STARTUPCORE == BAMBOO_NUM_OF_CORE) ...
1451 #ifdef DEBUG
1452     BAMBOO_DEBUGPRINT(0xed0a);
1453 #endif
1454
1455     if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1456 #ifdef DEBUG
1457       BAMBOO_DEBUGPRINT(0xed0b);
1458 #endif
1459       return;
1460     }
1461   }       // while(MARKPHASE == gcphase)
1462 } // mark()
1463
1464 inline void compact2Heaptophelper_I(int coren,
1465                                     int* p,
1466                                     int* numblocks,
1467                                     int* remain) {
1468   int b;
1469   int memneed = gcrequiredmems[coren] + BAMBOO_CACHE_LINE_SIZE;
1470   if(STARTUPCORE == coren) {
1471     gctomove = true;
1472     gcmovestartaddr = *p;
1473     gcdstcore = gctopcore;
1474     gcblock2fill = *numblocks + 1;
1475   } else {
1476     send_msg_4(coren, GCMOVESTART, gctopcore, *p, (*numblocks) + 1, false);
1477   }
1478 #ifdef DEBUG
1479   BAMBOO_DEBUGPRINT_REG(coren);
1480   BAMBOO_DEBUGPRINT_REG(gctopcore);
1481   BAMBOO_DEBUGPRINT_REG(*p);
1482   BAMBOO_DEBUGPRINT_REG(*numblocks+1);
1483 #endif
1484   if(memneed < *remain) {
1485 #ifdef DEBUG
1486     BAMBOO_DEBUGPRINT(0xd104);
1487 #endif
1488     *p = *p + memneed;
1489     gcrequiredmems[coren] = 0;
1490     gcloads[gctopcore] += memneed;
1491     *remain = *remain - memneed;
1492   } else {
1493 #ifdef DEBUG
1494     BAMBOO_DEBUGPRINT(0xd105);
1495 #endif
1496     // next available block
1497     *p = *p + *remain;
1498     gcfilledblocks[gctopcore] += 1;
1499     int newbase = 0;
1500     BASEPTR(gctopcore, gcfilledblocks[gctopcore], &newbase);
1501     gcloads[gctopcore] = newbase;
1502     gcrequiredmems[coren] -= *remain - BAMBOO_CACHE_LINE_SIZE;
1503     gcstopblock[gctopcore]++;
1504     gctopcore = NEXTTOPCORE(gctopblock);
1505     gctopblock++;
1506     *numblocks = gcstopblock[gctopcore];
1507     *p = gcloads[gctopcore];
1508     BLOCKINDEX(*p, &b);
1509     *remain=(b<NUMCORES4GC) ?
1510              ((BAMBOO_SMEM_SIZE_L)-((*p)%(BAMBOO_SMEM_SIZE_L)))
1511              : ((BAMBOO_SMEM_SIZE)-((*p)%(BAMBOO_SMEM_SIZE)));
1512 #ifdef DEBUG
1513     BAMBOO_DEBUGPRINT(0xd106);
1514     BAMBOO_DEBUGPRINT_REG(gctopcore);
1515     BAMBOO_DEBUGPRINT_REG(*p);
1516     BAMBOO_DEBUGPRINT_REG(b);
1517     BAMBOO_DEBUGPRINT_REG(*remain);
1518 #endif
1519   }       // if(memneed < remain)
1520   gcmovepending--;
1521 } // void compact2Heaptophelper_I(int, int*, int*, int*)
1522
1523 inline void compact2Heaptop() {
1524   // no cores with spare mem and some cores are blocked with pending move
1525   // find the current heap top and make them move to the heap top
1526   int p;
1527   int numblocks = gcfilledblocks[gctopcore];
1528   //BASEPTR(gctopcore, numblocks, &p);
1529   p = gcloads[gctopcore];
1530   int b;
1531   BLOCKINDEX(p, &b);
1532   int remain = (b<NUMCORES4GC) ?
1533                ((BAMBOO_SMEM_SIZE_L)-(p%(BAMBOO_SMEM_SIZE_L)))
1534                : ((BAMBOO_SMEM_SIZE)-(p%(BAMBOO_SMEM_SIZE)));
1535   // check if the top core finishes
1536   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1537   if(gccorestatus[gctopcore] != 0) {
1538 #ifdef DEBUG
1539     BAMBOO_DEBUGPRINT(0xd101);
1540     BAMBOO_DEBUGPRINT_REG(gctopcore);
1541 #endif
1542     // let the top core finishes its own work first
1543     compact2Heaptophelper_I(gctopcore, &p, &numblocks, &remain);
1544     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1545     return;
1546   }
1547   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1548
1549 #ifdef DEBUG
1550   BAMBOO_DEBUGPRINT(0xd102);
1551   BAMBOO_DEBUGPRINT_REG(gctopcore);
1552   BAMBOO_DEBUGPRINT_REG(p);
1553   BAMBOO_DEBUGPRINT_REG(b);
1554   BAMBOO_DEBUGPRINT_REG(remain);
1555 #endif
1556   for(int i = 0; i < NUMCORES4GC; i++) {
1557     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1558     if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0)) {
1559 #ifdef DEBUG
1560       BAMBOO_DEBUGPRINT(0xd103);
1561 #endif
1562       compact2Heaptophelper_I(i, &p, &numblocks, &remain);
1563       if(gccorestatus[gctopcore] != 0) {
1564 #ifdef DEBUG
1565         BAMBOO_DEBUGPRINT(0xd101);
1566         BAMBOO_DEBUGPRINT_REG(gctopcore);
1567 #endif
1568         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1569         // the top core is not free now
1570         return;
1571       }
1572     }             // if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0))
1573     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1574   }       // for(i = 0; i < NUMCORES4GC; i++)
1575 #ifdef DEBUG
1576   BAMBOO_DEBUGPRINT(0xd106);
1577 #endif
1578 } // void compact2Heaptop()
1579
1580 inline void resolvePendingMoveRequest() {
1581 #ifdef DEBUG
1582   BAMBOO_DEBUGPRINT(0xeb01);
1583 #endif
1584 #ifdef DEBUG
1585   BAMBOO_DEBUGPRINT(0xeeee);
1586   for(int k = 0; k < NUMCORES4GC; k++) {
1587     BAMBOO_DEBUGPRINT(0xf000+k);
1588     BAMBOO_DEBUGPRINT_REG(gccorestatus[k]);
1589     BAMBOO_DEBUGPRINT_REG(gcloads[k]);
1590     BAMBOO_DEBUGPRINT_REG(gcfilledblocks[k]);
1591     BAMBOO_DEBUGPRINT_REG(gcstopblock[k]);
1592   }
1593   BAMBOO_DEBUGPRINT(0xffff);
1594 #endif
1595   int i;
1596   int j;
1597   bool nosparemem = true;
1598   bool haspending = false;
1599   bool hasrunning = false;
1600   bool noblock = false;
1601   int dstcore = 0;       // the core who need spare mem
1602   int sourcecore = 0;       // the core who has spare mem
1603   for(i = j = 0; (i < NUMCORES4GC) && (j < NUMCORES4GC); ) {
1604     if(nosparemem) {
1605       // check if there are cores with spare mem
1606       if(gccorestatus[i] == 0) {
1607         // finished working, check if it still have spare mem
1608         if(gcfilledblocks[i] < gcstopblock[i]) {
1609           // still have spare mem
1610           nosparemem = false;
1611           sourcecore = i;
1612         }                         // if(gcfilledblocks[i] < gcstopblock[i]) else ...
1613       }
1614       i++;
1615     }             // if(nosparemem)
1616     if(!haspending) {
1617       if(gccorestatus[j] != 0) {
1618         // not finished, check if it has pending move requests
1619         if((gcfilledblocks[j]==gcstopblock[j])&&(gcrequiredmems[j]>0)) {
1620           dstcore = j;
1621           haspending = true;
1622         } else {
1623           hasrunning = true;
1624         }                         // if((gcfilledblocks[i] == gcstopblock[i])...) else ...
1625       }                   // if(gccorestatus[i] == 0) else ...
1626       j++;
1627     }             // if(!haspending)
1628     if(!nosparemem && haspending) {
1629       // find match
1630       int tomove = 0;
1631       int startaddr = 0;
1632       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1633       gcrequiredmems[dstcore] = assignSpareMem_I(sourcecore,
1634                                                  gcrequiredmems[dstcore],
1635                                                  &tomove,
1636                                                  &startaddr);
1637       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1638 #ifdef DEBUG
1639       BAMBOO_DEBUGPRINT(0xeb02);
1640       BAMBOO_DEBUGPRINT_REG(sourcecore);
1641       BAMBOO_DEBUGPRINT_REG(dstcore);
1642       BAMBOO_DEBUGPRINT_REG(startaddr);
1643       BAMBOO_DEBUGPRINT_REG(tomove);
1644 #endif
1645       if(STARTUPCORE == dstcore) {
1646 #ifdef DEBUG
1647         BAMBOO_DEBUGPRINT(0xeb03);
1648 #endif
1649         gcdstcore = sourcecore;
1650         gctomove = true;
1651         gcmovestartaddr = startaddr;
1652         gcblock2fill = tomove;
1653       } else {
1654 #ifdef DEBUG
1655         BAMBOO_DEBUGPRINT(0xeb04);
1656 #endif
1657         send_msg_4(dstcore, GCMOVESTART, sourcecore,
1658                    startaddr, tomove, false);
1659       }
1660       gcmovepending--;
1661       nosparemem = true;
1662       haspending = false;
1663       noblock = true;
1664     }
1665   }       // for(i = 0; i < NUMCORES4GC; i++)
1666 #ifdef DEBUG
1667   BAMBOO_DEBUGPRINT(0xcccc);
1668   BAMBOO_DEBUGPRINT_REG(hasrunning);
1669   BAMBOO_DEBUGPRINT_REG(haspending);
1670   BAMBOO_DEBUGPRINT_REG(noblock);
1671 #endif
1672
1673   if(!hasrunning && !noblock) {
1674     gcphase = SUBTLECOMPACTPHASE;
1675     compact2Heaptop();
1676   }
1677
1678 } // void resovePendingMoveRequest()
1679
1680 struct moveHelper {
1681   int numblocks;       // block num for heap
1682   INTPTR base;       // base virtual address of current heap block
1683   INTPTR ptr;       // virtual address of current heap top
1684   int offset;       // offset in current heap block
1685   int blockbase;       // virtual address of current small block to check
1686   int blockbound;       // bound virtual address of current small blcok
1687   int sblockindex;       // index of the small blocks
1688   int top;       // real size of current heap block to check
1689   int bound;       // bound size of current heap block to check
1690 }; // struct moveHelper
1691
1692 // if out of boundary of valid shared memory, return false, else return true
1693 inline bool nextSBlock(struct moveHelper * orig) {
1694   orig->blockbase = orig->blockbound;
1695   bool sbchanged = false;
1696 #ifdef DEBUG
1697   BAMBOO_DEBUGPRINT(0xecc0);
1698   BAMBOO_DEBUGPRINT_REG(orig->blockbase);
1699   BAMBOO_DEBUGPRINT_REG(orig->blockbound);
1700   BAMBOO_DEBUGPRINT_REG(orig->bound);
1701   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1702 #endif
1703 outernextSBlock:
1704   // check if across a big block
1705   if((orig->blockbase >= orig->bound) || (orig->ptr >= orig->bound)
1706      || ((orig->ptr != NULL) && (*((int*)orig->ptr))==0)
1707      || ((*((int*)orig->blockbase))==0)) {
1708 innernextSBlock:
1709     // end of current heap block, jump to next one
1710     orig->numblocks++;
1711 #ifdef DEBUG
1712     BAMBOO_DEBUGPRINT(0xecc1);
1713     BAMBOO_DEBUGPRINT_REG(orig->numblocks);
1714 #endif
1715     BASEPTR(BAMBOO_NUM_OF_CORE, orig->numblocks, &(orig->base));
1716 #ifdef DEBUG
1717     BAMBOO_DEBUGPRINT(orig->base);
1718 #endif
1719     if(orig->base >= BAMBOO_BASE_VA + BAMBOO_SHARED_MEM_SIZE) {
1720       // out of boundary
1721       orig->ptr = orig->base;                   // set current ptr to out of boundary too
1722       return false;
1723     }
1724     orig->bound = orig->base + BAMBOO_SMEM_SIZE;
1725     orig->blockbase = orig->base;
1726     orig->sblockindex = (orig->blockbase-BAMBOO_BASE_VA)/BAMBOO_SMEM_SIZE;
1727     sbchanged = true;
1728     int blocknum = 0;
1729     BLOCKINDEX(orig->base, &blocknum);
1730     if(bamboo_smemtbl[blocknum] == 0) {
1731       // goto next block
1732       goto innernextSBlock;
1733     }
1734   } else if(0 == (orig->blockbase%BAMBOO_SMEM_SIZE)) {
1735     orig->sblockindex += 1;
1736     sbchanged = true;
1737   }       // if((orig->blockbase >= orig->bound) || (orig->ptr >= orig->bound)...
1738
1739   // check if this sblock should be skipped or have special start point
1740   if(gcsbstarttbl[orig->sblockindex] == -1) {
1741     // goto next sblock
1742 #ifdef DEBUG
1743     BAMBOO_DEBUGPRINT(0xecc2);
1744 #endif
1745     orig->sblockindex += 1;
1746     orig->blockbase += BAMBOO_SMEM_SIZE;
1747     goto outernextSBlock;
1748   } else if((gcsbstarttbl[orig->sblockindex] != 0)
1749             && (sbchanged)) {
1750     // the first time to access this SBlock
1751 #ifdef DEBUG
1752     BAMBOO_DEBUGPRINT(0xecc3);
1753 #endif
1754     // not start from the very beginning
1755     orig->blockbase = gcsbstarttbl[orig->sblockindex];
1756   }       // if(gcsbstarttbl[orig->sblockindex] == -1) else ...
1757
1758   // setup information for this sblock
1759   orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1760   orig->offset = BAMBOO_CACHE_LINE_SIZE;
1761   orig->ptr = orig->blockbase + orig->offset;
1762 #ifdef DEBUG
1763   BAMBOO_DEBUGPRINT(0xecc4);
1764   BAMBOO_DEBUGPRINT_REG(orig->base);
1765   BAMBOO_DEBUGPRINT_REG(orig->bound);
1766   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1767   BAMBOO_DEBUGPRINT_REG(orig->blockbound);
1768   BAMBOO_DEBUGPRINT_REG(orig->blockbase);
1769   BAMBOO_DEBUGPRINT_REG(orig->offset);
1770 #endif
1771   if(orig->ptr >= orig->bound) {
1772     // met a lobj, move to next block
1773     goto innernextSBlock;
1774   }
1775
1776   return true;
1777 } // bool nextSBlock(struct moveHelper * orig)
1778
1779 // return false if there are no available data to compact
1780 inline bool initOrig_Dst(struct moveHelper * orig,
1781                          struct moveHelper * to) {
1782   // init the dst ptr
1783   to->numblocks = 0;
1784   to->top = to->offset = BAMBOO_CACHE_LINE_SIZE;
1785   to->bound = BAMBOO_SMEM_SIZE_L;
1786   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1787
1788 #ifdef DEBUG
1789   BAMBOO_DEBUGPRINT(0xef01);
1790   BAMBOO_DEBUGPRINT_REG(to->base);
1791 #endif
1792   to->ptr = to->base + to->offset;
1793
1794   // init the orig ptr
1795   orig->numblocks = 0;
1796   orig->base = to->base;
1797   orig->bound = to->base + BAMBOO_SMEM_SIZE_L;
1798   orig->blockbase = orig->base;
1799   orig->sblockindex = (orig->base - BAMBOO_BASE_VA) / BAMBOO_SMEM_SIZE;
1800 #ifdef DEBUG
1801   BAMBOO_DEBUGPRINT(0xef02);
1802   BAMBOO_DEBUGPRINT_REG(orig->base);
1803   BAMBOO_DEBUGPRINT_REG(orig->sblockindex);
1804   BAMBOO_DEBUGPRINT_REG(gcsbstarttbl);
1805   BAMBOO_DEBUGPRINT_REG(gcsbstarttbl[orig->sblockindex]);
1806 #endif
1807
1808   if(gcsbstarttbl[orig->sblockindex] == -1) {
1809 #ifdef DEBUG
1810     BAMBOO_DEBUGPRINT(0xef03);
1811 #endif
1812     // goto next sblock
1813     orig->blockbound =
1814       BAMBOO_BASE_VA+BAMBOO_SMEM_SIZE*(orig->sblockindex+1);
1815     return nextSBlock(orig);
1816   } else if(gcsbstarttbl[orig->sblockindex] != 0) {
1817 #ifdef DEBUG
1818     BAMBOO_DEBUGPRINT(0xef04);
1819 #endif
1820     orig->blockbase = gcsbstarttbl[orig->sblockindex];
1821   }
1822 #ifdef DEBUG
1823   BAMBOO_DEBUGPRINT(0xef05);
1824 #endif
1825   orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1826   orig->offset = BAMBOO_CACHE_LINE_SIZE;
1827   orig->ptr = orig->blockbase + orig->offset;
1828 #ifdef DEBUG
1829   BAMBOO_DEBUGPRINT(0xef06);
1830   BAMBOO_DEBUGPRINT_REG(orig->base);
1831 #endif
1832   return true;
1833 } // bool initOrig_Dst(struct moveHelper * orig, struct moveHelper * to)
1834
1835 inline void nextBlock(struct moveHelper * to) {
1836   to->top = to->bound + BAMBOO_CACHE_LINE_SIZE;       // header!
1837   to->bound += BAMBOO_SMEM_SIZE;
1838   to->numblocks++;
1839   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1840   to->offset = BAMBOO_CACHE_LINE_SIZE;
1841   to->ptr = to->base + to->offset;
1842 } // void nextBlock(struct moveHelper * to)
1843
1844 // endaddr does not contain spaces for headers
1845 inline bool moveobj(struct moveHelper * orig,
1846                     struct moveHelper * to,
1847                     int stopblock) {
1848   if(stopblock == 0) {
1849     return true;
1850   }
1851
1852 #ifdef DEBUG
1853   BAMBOO_DEBUGPRINT(0xe201);
1854   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1855   BAMBOO_DEBUGPRINT_REG(to->ptr);
1856 #endif
1857
1858   int type = 0;
1859   int size = 0;
1860   int mark = 0;
1861   int isize = 0;
1862 innermoveobj:
1863   while((char)(*((int*)(orig->ptr))) == (char)(-2)) {
1864     orig->ptr = (int*)(orig->ptr) + 1;
1865   }
1866   if((orig->ptr > orig->bound) || (orig->ptr == orig->blockbound)) {
1867     if(!nextSBlock(orig)) {
1868       // finished, no more data
1869       return true;
1870     }
1871     goto innermoveobj;
1872   }
1873 #ifdef DEBUG
1874   BAMBOO_DEBUGPRINT(0xe202);
1875   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1876   BAMBOO_DEBUGPRINT(((int *)(orig->ptr))[0]);
1877 #endif
1878   // check the obj's type, size and mark flag
1879   type = ((int *)(orig->ptr))[0];
1880   size = 0;
1881   if(type == 0) {
1882     // end of this block, go to next one
1883     if(!nextSBlock(orig)) {
1884       // finished, no more data
1885       return true;
1886     }
1887     goto innermoveobj;
1888   } else if(type < NUMCLASSES) {
1889     // a normal object
1890     size = classsize[type];
1891   } else {
1892     // an array
1893     struct ArrayObject *ao=(struct ArrayObject *)(orig->ptr);
1894     int elementsize=classsize[type];
1895     int length=ao->___length___;
1896     size=sizeof(struct ArrayObject)+length*elementsize;
1897   }
1898   mark = ((int *)(orig->ptr))[6];
1899   bool isremote = ((((int *)(orig->ptr))[6] & REMOTEM) != 0);
1900 #ifdef DEBUG
1901   BAMBOO_DEBUGPRINT(0xe203);
1902   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1903   BAMBOO_DEBUGPRINT_REG(size);
1904 #endif
1905   ALIGNSIZE(size, &isize);       // no matter is the obj marked or not
1906                                  // should be able to across it
1907   if((mark & MARKED) != 0) {
1908 #ifdef DEBUG
1909     BAMBOO_DEBUGPRINT(0xe204);
1910 #endif
1911     // marked obj, copy it to current heap top
1912     // check to see if remaining space is enough
1913     if(to->top + isize > to->bound) {
1914       // fill 0 indicating the end of this block
1915       BAMBOO_MEMSET_WH(to->ptr,  '\0', to->bound - to->top);
1916       // fill the header of this block and then go to next block
1917       to->offset += to->bound - to->top;
1918       BAMBOO_MEMSET_WH(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
1919       (*((int*)(to->base))) = to->offset;
1920       nextBlock(to);
1921       if(stopblock == to->numblocks) {
1922         // already fulfilled the block
1923         return true;
1924       }                   // if(stopblock == to->numblocks)
1925     }             // if(to->top + isize > to->bound)
1926     // set the mark field to 2, indicating that this obj has been moved
1927     // and need to be flushed
1928     ((int *)(orig->ptr))[6] = COMPACTED;
1929     if(to->ptr != orig->ptr) {
1930       if((int)(orig->ptr) < (int)(to->ptr)+size) {
1931         memmove(to->ptr, orig->ptr, size);
1932       } else {
1933         //BAMBOO_WRITE_HINT_CACHE(to->ptr, size);
1934         memcpy(to->ptr, orig->ptr, size);
1935       }
1936       // fill the remaining space with -2
1937       BAMBOO_MEMSET_WH(to->ptr+size, -2, isize-size);
1938     }
1939     // store mapping info
1940     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1941     //mgchashInsert_I(orig->ptr, to->ptr);
1942     RuntimeHashadd_I(gcpointertbl, orig->ptr, to->ptr);
1943         if(isremote) {
1944           // add to the sharedptbl
1945           if(gcsharedptbl != NULL) {
1946                 //GCSharedHashadd_I(gcsharedptbl, orig->ptr, to->ptr);
1947                 mgcsharedhashInsert_I(gcsharedptbl, orig->ptr, to->ptr);
1948           }
1949         }
1950     //MGCHashadd_I(gcpointertbl, orig->ptr, to->ptr);
1951     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1952     //}
1953 #ifdef DEBUG
1954     BAMBOO_DEBUGPRINT(0xcdce);
1955     BAMBOO_DEBUGPRINT_REG(orig->ptr);
1956     BAMBOO_DEBUGPRINT_REG(to->ptr);
1957 #endif
1958     gccurr_heaptop -= isize;
1959     to->ptr += isize;
1960     to->offset += isize;
1961     to->top += isize;
1962     if(to->top == to->bound) {
1963       // fill the header of this block and then go to next block
1964       BAMBOO_MEMSET_WH(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
1965       (*((int*)(to->base))) = to->offset;
1966       nextBlock(to);
1967     }
1968   }       // if(mark == 1)
1969 #ifdef DEBUG
1970   BAMBOO_DEBUGPRINT(0xe205);
1971 #endif
1972   // move to next obj
1973   orig->ptr += size;
1974
1975 #ifdef DEBUG
1976   BAMBOO_DEBUGPRINT_REG(isize);
1977   BAMBOO_DEBUGPRINT_REG(size);
1978   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1979   BAMBOO_DEBUGPRINT_REG(orig->bound);
1980 #endif
1981   if((orig->ptr > orig->bound) || (orig->ptr == orig->blockbound)) {
1982 #ifdef DEBUG
1983     BAMBOO_DEBUGPRINT(0xe206);
1984 #endif
1985     if(!nextSBlock(orig)) {
1986       // finished, no more data
1987       return true;
1988     }
1989   }
1990 #ifdef DEBUG
1991   BAMBOO_DEBUGPRINT(0xe207);
1992   BAMBOO_DEBUGPRINT_REG(orig->ptr);
1993 #endif
1994   return false;
1995 } //bool moveobj(struct moveHelper* orig,struct moveHelper* to,int* endaddr)
1996
1997 // should be invoked with interrupt closed
1998 inline int assignSpareMem_I(int sourcecore,
1999                             int * requiredmem,
2000                             int * tomove,
2001                             int * startaddr) {
2002   int b = 0;
2003   BLOCKINDEX(gcloads[sourcecore], &b);
2004   int boundptr = (b<NUMCORES4GC) ? ((b+1)*BAMBOO_SMEM_SIZE_L)
2005                  : (BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES4GC+1)*BAMBOO_SMEM_SIZE);
2006   int remain = boundptr - gcloads[sourcecore];
2007   int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
2008   *startaddr = gcloads[sourcecore];
2009   *tomove = gcfilledblocks[sourcecore] + 1;
2010   if(memneed < remain) {
2011     gcloads[sourcecore] += memneed;
2012     return 0;
2013   } else {
2014     // next available block
2015     gcfilledblocks[sourcecore] += 1;
2016     int newbase = 0;
2017     BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
2018     gcloads[sourcecore] = newbase;
2019     return requiredmem-remain;
2020   }
2021 } // int assignSpareMem_I(int ,int * , int * , int * )
2022
2023 // should be invoked with interrupt closed
2024 inline bool gcfindSpareMem_I(int * startaddr,
2025                              int * tomove,
2026                              int * dstcore,
2027                              int requiredmem,
2028                              int requiredcore) {
2029   for(int k = 0; k < NUMCORES4GC; k++) {
2030     if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
2031       // check if this stopped core has enough mem
2032       assignSpareMem_I(k, requiredmem, tomove, startaddr);
2033       *dstcore = k;
2034       return true;
2035     }
2036   }
2037   // if can not find spare mem right now, hold the request
2038   gcrequiredmems[requiredcore] = requiredmem;
2039   gcmovepending++;
2040   return false;
2041 } //bool gcfindSpareMem_I(int* startaddr,int* tomove,int mem,int core)
2042
2043 inline bool compacthelper(struct moveHelper * orig,
2044                           struct moveHelper * to,
2045                           int * filledblocks,
2046                           int * heaptopptr,
2047                           bool * localcompact) {
2048   // scan over all objs in this block, compact the marked objs
2049   // loop stop when finishing either scanning all active objs or
2050   // fulfilled the gcstopblock
2051 #ifdef DEBUG
2052   BAMBOO_DEBUGPRINT(0xe101);
2053   BAMBOO_DEBUGPRINT_REG(gcblock2fill);
2054   BAMBOO_DEBUGPRINT_REG(gcmarkedptrbound);
2055 #endif
2056 innercompact:
2057   while(orig->ptr < gcmarkedptrbound) {
2058     bool stop = moveobj(orig, to, gcblock2fill);
2059     if(stop) {
2060       break;
2061     }
2062   }
2063   // if no objs have been compact, do nothing,
2064   // otherwise, fill the header of this block
2065   if(to->offset > BAMBOO_CACHE_LINE_SIZE) {
2066     BAMBOO_MEMSET_WH(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
2067     (*((int*)(to->base))) = to->offset;
2068   } else {
2069     to->offset = 0;
2070     to->ptr = to->base;
2071     to->top -= BAMBOO_CACHE_LINE_SIZE;
2072   }       // if(to->offset > BAMBOO_CACHE_LINE_SIZE) else ...
2073   if(*localcompact) {
2074     *heaptopptr = to->ptr;
2075     *filledblocks = to->numblocks;
2076   }
2077 #ifdef DEBUG
2078   BAMBOO_DEBUGPRINT(0xe102);
2079   BAMBOO_DEBUGPRINT_REG(orig->ptr);
2080   BAMBOO_DEBUGPRINT_REG(gcmarkedptrbound);
2081   BAMBOO_DEBUGPRINT_REG(*heaptopptr);
2082   BAMBOO_DEBUGPRINT_REG(*filledblocks);
2083   BAMBOO_DEBUGPRINT_REG(gccurr_heaptop);
2084 #endif
2085
2086   // send msgs to core coordinator indicating that the compact is finishing
2087   // send compact finish message to core coordinator
2088   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
2089     gcfilledblocks[BAMBOO_NUM_OF_CORE] = *filledblocks;
2090     gcloads[BAMBOO_NUM_OF_CORE] = *heaptopptr;
2091     if(orig->ptr < gcmarkedptrbound) {
2092 #ifdef DEBUG
2093       BAMBOO_DEBUGPRINT(0xe103);
2094 #endif
2095       // ask for more mem
2096       gctomove = false;
2097       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2098       if(gcfindSpareMem_I(&gcmovestartaddr, &gcblock2fill, &gcdstcore,
2099                           gccurr_heaptop, BAMBOO_NUM_OF_CORE)) {
2100 #ifdef DEBUG
2101         BAMBOO_DEBUGPRINT(0xe104);
2102 #endif
2103         gctomove = true;
2104       } else {
2105         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2106 #ifdef DEBUG
2107         BAMBOO_DEBUGPRINT(0xe105);
2108 #endif
2109         return false;
2110       }
2111       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2112     } else {
2113 #ifdef DEBUG
2114       BAMBOO_DEBUGPRINT(0xe106);
2115 #endif
2116       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
2117       gctomove = false;
2118       return true;
2119     }
2120   } else {
2121     if(orig->ptr < gcmarkedptrbound) {
2122 #ifdef DEBUG
2123       BAMBOO_DEBUGPRINT(0xe107);
2124 #endif
2125       // ask for more mem
2126       gctomove = false;
2127       send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
2128                  *filledblocks, *heaptopptr, gccurr_heaptop, false);
2129     } else {
2130 #ifdef DEBUG
2131       BAMBOO_DEBUGPRINT(0xe108);
2132       BAMBOO_DEBUGPRINT_REG(*heaptopptr);
2133 #endif
2134       // finish compacting
2135       send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
2136                  *filledblocks, *heaptopptr, 0, false);
2137     }
2138   }       // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
2139
2140   if(orig->ptr < gcmarkedptrbound) {
2141 #ifdef DEBUG
2142     BAMBOO_DEBUGPRINT(0xe109);
2143 #endif
2144     // still have unpacked obj
2145     while(true) {
2146       if(gctomove) {
2147         break;
2148       }
2149     }
2150     ;
2151     gctomove = false;
2152 #ifdef DEBUG
2153     BAMBOO_DEBUGPRINT(0xe10a);
2154 #endif
2155
2156     to->ptr = gcmovestartaddr;
2157     to->numblocks = gcblock2fill - 1;
2158     to->bound = (to->numblocks==0) ?
2159                 BAMBOO_SMEM_SIZE_L :
2160                 BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
2161     BASEPTR(gcdstcore, to->numblocks, &(to->base));
2162     to->offset = to->ptr - to->base;
2163     to->top = (to->numblocks==0) ?
2164               (to->offset) : (to->bound-BAMBOO_SMEM_SIZE+to->offset);
2165     to->base = to->ptr;
2166     to->offset = BAMBOO_CACHE_LINE_SIZE;
2167     to->ptr += to->offset;             // for header
2168     to->top += to->offset;
2169     if(gcdstcore == BAMBOO_NUM_OF_CORE) {
2170       *localcompact = true;
2171     } else {
2172       *localcompact = false;
2173     }
2174     goto innercompact;
2175   }
2176 #ifdef DEBUG
2177   BAMBOO_DEBUGPRINT(0xe10b);
2178 #endif
2179   return true;
2180 } // void compacthelper()
2181
2182 inline void compact() {
2183   if(COMPACTPHASE != gcphase) {
2184     BAMBOO_EXIT(0xb102);
2185   }
2186
2187   // initialize pointers for comapcting
2188   struct moveHelper * orig =
2189     (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
2190   struct moveHelper * to =
2191     (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
2192
2193   if(!initOrig_Dst(orig, to)) {
2194     // no available data to compact
2195     // send compact finish msg to STARTUP core
2196 #ifdef DEBUG
2197     BAMBOO_DEBUGPRINT(0xe001);
2198     BAMBOO_DEBUGPRINT_REG(to->base);
2199 #endif
2200     send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
2201                0, to->base, 0, false);
2202     RUNFREE(orig);
2203     RUNFREE(to);
2204     return;
2205   }
2206
2207   int filledblocks = 0;
2208   INTPTR heaptopptr = 0;
2209   bool localcompact = true;
2210   compacthelper(orig, to, &filledblocks, &heaptopptr, &localcompact);
2211
2212   RUNFREE(orig);
2213   RUNFREE(to);
2214 } // compact()
2215
2216 // if return NULL, means
2217 //   1. objptr is NULL
2218 //   2. objptr is not a shared obj
2219 // in these cases, remain the original value is OK
2220 inline void * flushObj(void * objptr) {
2221 #ifdef DEBUG
2222   BAMBOO_DEBUGPRINT(0xe401);
2223 #endif
2224   if(objptr == NULL) {
2225     return NULL;
2226   }
2227   void * dstptr = NULL;
2228   if(ISSHAREDOBJ(objptr)) {
2229 #ifdef DEBUG
2230     BAMBOO_DEBUGPRINT(0xe402);
2231     BAMBOO_DEBUGPRINT_REG(objptr);
2232 #endif
2233     // a shared obj ptr, change to new address
2234     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2235 #ifdef GC_PROFILE
2236     // TODO unsigned long long ttime = BAMBOO_GET_EXE_TIME();
2237 #endif
2238     //dstptr = mgchashSearch(objptr);
2239     RuntimeHashget(gcpointertbl, objptr, &dstptr);
2240 #ifdef GC_PROFILE
2241     // TODO flushstalltime += BAMBOO_GET_EXE_TIME()-ttime;
2242 #endif
2243     //MGCHashget(gcpointertbl, objptr, &dstptr);
2244     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2245 #ifdef DEBUG
2246     BAMBOO_DEBUGPRINT_REG(dstptr);
2247 #endif
2248
2249     if(NULL == dstptr) {
2250       // no mapping info
2251 #ifdef DEBUG
2252       BAMBOO_DEBUGPRINT(0xe403);
2253       BAMBOO_DEBUGPRINT_REG(objptr);
2254       BAMBOO_DEBUGPRINT_REG(hostcore(objptr));
2255 #endif
2256       if(hostcore(objptr) == BAMBOO_NUM_OF_CORE) {
2257         // error! the obj is right on this core, but cannot find it
2258         BAMBOO_DEBUGPRINT_REG(objptr);
2259         BAMBOO_EXIT(0xb103);
2260         // assume that the obj has not been moved, use the original address
2261         //dstptr = objptr;
2262       } else {
2263                 int hostc = hostcore(objptr);
2264                 // check the corresponsing sharedptbl
2265                 BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2266                 //struct GCSharedHash * sptbl = gcrpointertbls[hostcore(objptr)];
2267                 mgcsharedhashtbl_t * sptbl = gcrpointertbls[hostc];
2268                 if(sptbl != NULL) {
2269                   //GCSharedHashget(sptbl, (int)objptr, &dstptr);
2270                   dstptr = mgcsharedhashSearch(sptbl, (int)objptr);
2271                   if(dstptr != NULL) {
2272                         RuntimeHashadd_I(gcpointertbl, (int)objptr, (int)dstptr);
2273                   }
2274                 }
2275                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2276
2277                 if(dstptr == NULL) {
2278                   // still can not get the mapping info,
2279                   // send msg to host core for the mapping info
2280                   gcobj2map = (int)objptr;
2281                   gcismapped = false;
2282                   gcmappedobj = NULL;
2283 #ifdef GC_PROFILE
2284         // TODO
2285         num_mapinforequest++;
2286         //unsigned long long ttime = BAMBOO_GET_EXE_TIME();
2287 #endif
2288 #ifdef GC_PROFILE
2289         unsigned long long ttimet = BAMBOO_GET_EXE_TIME();
2290 #endif
2291                   // the first time require the mapping, send msg to the hostcore
2292                   // for the mapping info
2293                   send_msg_3(hostc, GCMAPREQUEST, (int)objptr,
2294                           BAMBOO_NUM_OF_CORE, false);
2295                   while(true) {
2296                         if(gcismapped) {
2297                           break;
2298                         }
2299                   }
2300 #ifdef GC_PROFILE
2301         flushstalltime_i += BAMBOO_GET_EXE_TIME()-ttimet;
2302 #endif
2303 #ifdef GC_PROFILE
2304         // TODO
2305         //flushstalltime += BAMBOO_GET_EXE_TIME() - ttime;
2306 #endif
2307                   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2308                   //dstptr = mgchashSearch(objptr);
2309                   RuntimeHashget(gcpointertbl, objptr, &dstptr);
2310                   //MGCHashget(gcpointertbl, objptr, &dstptr);
2311                   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2312                 } // if(dstptr == NULL)
2313           }    // if(hostcore(objptr) == BAMBOO_NUM_OF_CORE) else ...
2314 #ifdef DEBUG
2315       BAMBOO_DEBUGPRINT_REG(dstptr);
2316 #endif
2317     }     // if(NULL == dstptr)
2318   }      // if(ISSHAREDOBJ(objptr))
2319          // if not a shared obj, return NULL to indicate no need to flush
2320 #ifdef DEBUG
2321   BAMBOO_DEBUGPRINT(0xe404);
2322 #endif
2323   return dstptr;
2324 } // void flushObj(void * objptr)
2325
2326 inline void flushRuntimeObj(struct garbagelist * stackptr) {
2327   int i,j;
2328   // flush current stack
2329   while(stackptr!=NULL) {
2330     for(i=0; i<stackptr->size; i++) {
2331       if(stackptr->array[i] != NULL) {
2332         void * dst = flushObj(stackptr->array[i]);
2333         if(dst != NULL) {
2334           stackptr->array[i] = dst;
2335         }
2336       }
2337     }
2338     stackptr=stackptr->next;
2339   }
2340
2341   // flush objectsets
2342   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
2343     for(i=0; i<NUMCLASSES; i++) {
2344       struct parameterwrapper ** queues =
2345         objectqueues[BAMBOO_NUM_OF_CORE][i];
2346       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
2347       for(j = 0; j < length; ++j) {
2348         struct parameterwrapper * parameter = queues[j];
2349         struct ObjectHash * set=parameter->objectset;
2350         struct ObjectNode * ptr=set->listhead;
2351         while(ptr!=NULL) {
2352           void * dst = flushObj((void *)ptr->key);
2353           if(dst != NULL) {
2354             ptr->key = dst;
2355           }
2356           ptr=ptr->lnext;
2357         }
2358         ObjectHashrehash(set);
2359       }
2360     }
2361   }
2362
2363   // flush current task descriptor
2364   if(currtpd != NULL) {
2365     for(i=0; i<currtpd->numParameters; i++) {
2366       void * dst = flushObj(currtpd->parameterArray[i]);
2367       if(dst != NULL) {
2368         currtpd->parameterArray[i] = dst;
2369       }
2370     }
2371   }
2372
2373   // flush active tasks
2374   if(activetasks != NULL) {
2375     struct genpointerlist * ptr=activetasks->list;
2376     while(ptr!=NULL) {
2377       struct taskparamdescriptor *tpd=ptr->src;
2378       int i;
2379       for(i=0; i<tpd->numParameters; i++) {
2380         void * dst = flushObj(tpd->parameterArray[i]);
2381         if(dst != NULL) {
2382           tpd->parameterArray[i] = dst;
2383         }
2384       }
2385       ptr=ptr->inext;
2386     }
2387     genrehash(activetasks);
2388   }
2389
2390   // flush cached transferred obj
2391   struct QueueItem * tmpobjptr =  getHead(&objqueue);
2392   while(tmpobjptr != NULL) {
2393     struct transObjInfo * objInfo =
2394       (struct transObjInfo *)(tmpobjptr->objectptr);
2395     void * dst = flushObj(objInfo->objptr);
2396     if(dst != NULL) {
2397       objInfo->objptr = dst;
2398     }
2399     tmpobjptr = getNextQueueItem(tmpobjptr);
2400   }
2401
2402   // flush cached objs to be transferred
2403   struct QueueItem * item = getHead(totransobjqueue);
2404   while(item != NULL) {
2405     struct transObjInfo * totransobj =
2406       (struct transObjInfo *)(item->objectptr);
2407     void * dst = flushObj(totransobj->objptr);
2408     if(dst != NULL) {
2409       totransobj->objptr = dst;
2410     }
2411     item = getNextQueueItem(item);
2412   }       // while(item != NULL)
2413
2414   // enqueue lock related info
2415   for(i = 0; i < runtime_locklen; ++i) {
2416     void * dst = flushObj(runtime_locks[i].redirectlock);
2417     if(dst != NULL) {
2418       runtime_locks[i].redirectlock = (int)dst;
2419     }
2420     if(runtime_locks[i].value != NULL) {
2421       void * dst=flushObj(runtime_locks[i].value);
2422       if(dst != NULL) {
2423         runtime_locks[i].value = (int)dst;
2424       }
2425     }
2426   }
2427
2428 } // void flushRuntimeObj(struct garbagelist * stackptr)
2429
2430 inline void transmappinginfo() {
2431   // inform the other cores the mapping info they need 
2432   /*struct RuntimeIterator* it_pointertbl = 
2433         RuntimeHashcreateiterator(gcpointertbl);
2434   while(RunhasNext(it_pointertbl)) {
2435         int obj = Runkey(it_pointertbl);
2436         struct nodemappinginfo * info = 
2437           (struct nodemappinginfo *)Runnext(it_pointertbl);
2438         int newptr = (int)info->ptr;
2439         struct requestcoreinfo * coreinfo = info->cores;
2440         info->cores = NULL;
2441         // send the mapping info to all requested cores
2442         while(coreinfo != NULL) {
2443           struct requestcoreinfo * tmp = coreinfo;
2444           coreinfo = coreinfo->next;
2445           send_msg_3(tmp->core, GCMAPINFO, obj, newptr, false);
2446           RUNFREE(tmp); // release the node
2447         }
2448   }*/
2449 /*  int core = (BAMBOO_NUM_OF_CORE + 1) % NUMCORESACTIVE;
2450   for(int i = 0; i < NUMCORESACTIVE - 1; i++) {
2451         for(int j = 1; j < gcmappingtbl[core][0]+1; j++) {
2452           int obj = gcmappingtbl[core][j];
2453           int newptr = 0;
2454           RuntimeHashget(gcpointertbl, obj, &newptr);
2455           send_msg_3(core, GCMAPINFO, obj, newptr, false);
2456           // TODO
2457           //tprintf("send mapping %x -> %x, %x \n", (int)obj, (int)newptr, i);
2458         }
2459         // TODO
2460         //tprintf("send mapping to core %d \n", core);
2461         core = (core + 1) % NUMCORESACTIVE;
2462   }
2463 */
2464
2465   // broadcast the sharedptbl pointer
2466   for(int i = 0; i < NUMCORESACTIVE; i++) {
2467         if(i != BAMBOO_NUM_OF_CORE) {
2468           send_msg_3(i, GCMAPTBL, gcsharedptbl, BAMBOO_NUM_OF_CORE, false);
2469         }
2470   }
2471
2472   // TODO
2473   //BAMBOO_DEBUGPRINT(0xeeee);
2474
2475   if(STARTUPCORE != BAMBOO_NUM_OF_CORE) {
2476         send_msg_2(STARTUPCORE, GCFINISHMAPINFO, BAMBOO_NUM_OF_CORE, false);
2477   }
2478 }
2479
2480 inline void flush(struct garbagelist * stackptr) {
2481 #ifdef GC_PROFILE
2482   /* TODO if(BAMBOO_NUM_OF_CORE == 0) {
2483     BAMBOO_DEBUGPRINT(0xcccc);
2484     BAMBOO_DEBUGPRINT_REG(BAMBOO_GET_EXE_TIME());
2485   }*/
2486 #endif
2487
2488   flushRuntimeObj(stackptr);
2489 #ifdef GC_PROFILE
2490   // TODO if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT_REG(BAMBOO_GET_EXE_TIME());
2491 #endif
2492
2493   while(true) {
2494     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2495     bool hasItems = gc_moreItems_I();
2496     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2497     if(!hasItems) {
2498       break;
2499     }
2500
2501 #ifdef DEBUG
2502     BAMBOO_DEBUGPRINT(0xe301);
2503 #endif
2504     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2505     void * ptr = gc_dequeue_I();
2506     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2507     if(ISSHAREDOBJ(ptr)) {
2508       // should be a local shared obj and should have mapping info
2509       ptr = flushObj(ptr);
2510 #ifdef DEBUG
2511       BAMBOO_DEBUGPRINT(0xe302);
2512       BAMBOO_DEBUGPRINT_REG(ptr);
2513       BAMBOO_DEBUGPRINT_REG(tptr);
2514       BAMBOO_DEBUGPRINT_REG(((int *)(tptr))[0]);
2515 #endif
2516       if(ptr == NULL) {
2517         BAMBOO_EXIT(0xb105);
2518       }
2519     } // if(ISSHAREDOBJ(ptr))
2520     if((!ISSHAREDOBJ(ptr)) || (((int *)(ptr))[6] == COMPACTED)) {
2521       int type = ((int *)(ptr))[0];
2522       // scan all pointers in ptr
2523       unsigned INTPTR * pointer;
2524       pointer=pointerarray[type];
2525 #ifdef DEBUG
2526       BAMBOO_DEBUGPRINT(0xe303);
2527       BAMBOO_DEBUGPRINT_REG(pointer);
2528 #endif
2529       if (pointer==0) {
2530         /* Array of primitives */
2531         /* Do nothing */
2532       } else if (((INTPTR)pointer)==1) {
2533 #ifdef DEBUG
2534         BAMBOO_DEBUGPRINT(0xe304);
2535 #endif
2536         /* Array of pointers */
2537         struct ArrayObject *ao=(struct ArrayObject *) ptr;
2538         int length=ao->___length___;
2539         int j;
2540         for(j=0; j<length; j++) {
2541 #ifdef DEBUG
2542           BAMBOO_DEBUGPRINT(0xe305);
2543 #endif
2544           void *objptr=
2545             ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
2546 #ifdef DEBUG
2547           BAMBOO_DEBUGPRINT_REG(objptr);
2548 #endif
2549           if(objptr != NULL) {
2550             void * dst = flushObj(objptr);
2551             if(dst != NULL) {
2552               ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] = dst;
2553             }
2554           }
2555         }
2556       } else {
2557 #ifdef DEBUG
2558         BAMBOO_DEBUGPRINT(0xe306);
2559 #endif
2560         INTPTR size=pointer[0];
2561         int i;
2562         for(i=1; i<=size; i++) {
2563 #ifdef DEBUG
2564           BAMBOO_DEBUGPRINT(0xe307);
2565 #endif
2566           unsigned int offset=pointer[i];
2567           void * objptr=*((void **)(((char *)ptr)+offset));
2568 #ifdef DEBUG
2569           BAMBOO_DEBUGPRINT_REG(objptr);
2570 #endif
2571           if(objptr != NULL) {
2572             void * dst = flushObj(objptr);
2573             if(dst != NULL) {
2574               *((void **)(((char *)ptr)+offset)) = dst;
2575             }
2576           }
2577         }                         // for(i=1; i<=size; i++)
2578       }                   // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
2579                           // restore the mark field, indicating that this obj has been flushed
2580       if(ISSHAREDOBJ(ptr)) {
2581         ((int *)(ptr))[6] = INIT;
2582       }
2583     }  // if((!ISSHAREDOBJ(ptr)) || (((int *)(ptr))[6] == COMPACTED))
2584   }       // while(gc_moreItems())
2585 #ifdef DEBUG
2586   BAMBOO_DEBUGPRINT(0xe308);
2587 #endif
2588 #ifdef GC_PROFILE
2589   // TODO if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT_REG(BAMBOO_GET_EXE_TIME());
2590 #endif
2591
2592   // TODO bug here: the startup core contains all lobjs' info, thus all the
2593   // lobjs are flushed in sequence.
2594   // flush lobjs
2595   while(gc_lobjmoreItems_I()) {
2596 #ifdef DEBUG
2597     BAMBOO_DEBUGPRINT(0xe309);
2598 #endif
2599     void * ptr = gc_lobjdequeue_I(NULL, NULL);
2600     ptr = flushObj(ptr);
2601 #ifdef DEBUG
2602     BAMBOO_DEBUGPRINT(0xe30a);
2603     BAMBOO_DEBUGPRINT_REG(ptr);
2604     BAMBOO_DEBUGPRINT_REG(tptr);
2605     BAMBOO_DEBUGPRINT_REG(((int *)(tptr))[0]);
2606 #endif
2607     if(ptr == NULL) {
2608       BAMBOO_EXIT(0x106);
2609     }
2610     if(((int *)(ptr))[6] == COMPACTED) {
2611       int type = ((int *)(ptr))[0];
2612       // scan all pointers in ptr
2613       unsigned INTPTR * pointer;
2614       pointer=pointerarray[type];
2615 #ifdef DEBUG
2616       BAMBOO_DEBUGPRINT(0xe30b);
2617       BAMBOO_DEBUGPRINT_REG(pointer);
2618 #endif
2619       if (pointer==0) {
2620         /* Array of primitives */
2621         /* Do nothing */
2622       } else if (((INTPTR)pointer)==1) {
2623 #ifdef DEBUG
2624         BAMBOO_DEBUGPRINT(0xe30c);
2625 #endif
2626         /* Array of pointers */
2627         struct ArrayObject *ao=(struct ArrayObject *) ptr;
2628         int length=ao->___length___;
2629         int j;
2630         for(j=0; j<length; j++) {
2631 #ifdef DEBUG
2632           BAMBOO_DEBUGPRINT(0xe30d);
2633 #endif
2634           void *objptr=
2635             ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
2636 #ifdef DEBUG
2637           BAMBOO_DEBUGPRINT_REG(objptr);
2638 #endif
2639           if(objptr != NULL) {
2640             void * dst = flushObj(objptr);
2641             if(dst != NULL) {
2642               ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] = dst;
2643             }
2644           }
2645         }
2646       } else {
2647 #ifdef DEBUG
2648         BAMBOO_DEBUGPRINT(0xe30e);
2649 #endif
2650         INTPTR size=pointer[0];
2651         int i;
2652         for(i=1; i<=size; i++) {
2653 #ifdef DEBUG
2654           BAMBOO_DEBUGPRINT(0xe30f);
2655 #endif
2656           unsigned int offset=pointer[i];
2657           void * objptr=*((void **)(((char *)ptr)+offset));
2658
2659 #ifdef DEBUG
2660           BAMBOO_DEBUGPRINT_REG(objptr);
2661 #endif
2662           if(objptr != NULL) {
2663             void * dst = flushObj(objptr);
2664             if(dst != NULL) {
2665               *((void **)(((char *)ptr)+offset)) = dst;
2666             }
2667           }
2668         }                         // for(i=1; i<=size; i++)
2669       }  // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
2670          // restore the mark field, indicating that this obj has been flushed
2671       ((int *)(ptr))[6] = INIT;
2672     }             // if(((int *)(ptr))[6] == COMPACTED)
2673   }       // while(gc_lobjmoreItems())
2674 #ifdef DEBUG
2675   BAMBOO_DEBUGPRINT(0xe310);
2676 #endif
2677 #ifdef GC_PROFILE
2678   // TODO if(BAMBOO_NUM_OF_CORE == 0) BAMBOO_DEBUGPRINT_REG(BAMBOO_GET_EXE_TIME());
2679 #endif
2680
2681   // send flush finish message to core coordinator
2682   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
2683     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
2684   } else {
2685     send_msg_2(STARTUPCORE, GCFINISHFLUSH, BAMBOO_NUM_OF_CORE, false);
2686   }
2687 #ifdef GC_PROFILE
2688   // TODO 
2689   if(BAMBOO_NUM_OF_CORE == 0) {
2690     BAMBOO_DEBUGPRINT(0xffff);
2691     BAMBOO_DEBUGPRINT_REG(num_mapinforequest);
2692     //BAMBOO_DEBUGPRINT_REG(flushstalltime);
2693     //BAMBOO_DEBUGPRINT_REG(num_mapinforequest_i);
2694     BAMBOO_DEBUGPRINT_REG(flushstalltime_i);
2695   }
2696   //BAMBOO_DEBUGPRINT_REG(flushstalltime);
2697 #endif
2698 #ifdef DEBUG
2699   BAMBOO_DEBUGPRINT(0xe311);
2700 #endif
2701 } // flush()
2702
2703 inline void gc_collect(struct garbagelist * stackptr) {
2704   // core collector routine
2705   while(true) {
2706     if(INITPHASE == gcphase) {
2707       break;
2708     }
2709   }
2710 #ifdef RAWPATH // TODO GC_DEBUG
2711   printf("(%X,%X) Do initGC\n", udn_tile_coord_x(), udn_tile_coord_y());
2712 #endif
2713   initGC();
2714   //send init finish msg to core coordinator
2715   send_msg_2(STARTUPCORE, GCFINISHINIT, BAMBOO_NUM_OF_CORE, false);
2716   while(true) {
2717     if(MARKPHASE == gcphase) {
2718       break;
2719     }
2720   }
2721 #ifdef RAWPATH // TODO GC_DEBUG
2722   printf("(%x,%x) Start mark phase\n", udn_tile_coord_x(), 
2723              udn_tile_coord_y());
2724 #endif
2725   mark(true, stackptr);
2726 #ifdef RAWPATH // TODO GC_DEBUG
2727   printf("(%x,%x) Finish mark phase, start compact phase\n", 
2728              udn_tile_coord_x(), udn_tile_coord_y());
2729 #endif
2730   compact();
2731 #ifdef RAWPATH // TODO GC_DEBUG
2732   printf("(%x,%x) Finish compact phase\n", udn_tile_coord_x(),
2733              udn_tile_coord_y());
2734 #endif
2735   while(true) {
2736         if(MAPPHASE == gcphase) {
2737           break;
2738         }
2739   }
2740 #ifdef RAWPATH // TODO GC_DEBUG
2741   printf("(%x,%x) Start map phase\n", udn_tile_coord_x(), 
2742              udn_tile_coord_y());
2743 #endif
2744   transmappinginfo();
2745 #ifdef RAWPATH // TODO GC_DEBUG
2746   printf("(%x,%x) Finish map phase\n", udn_tile_coord_x(),
2747              udn_tile_coord_y());
2748 #endif
2749   while(true) {
2750     if(FLUSHPHASE == gcphase) {
2751       break;
2752     }
2753   }
2754 #ifdef RAWPATH // TODO GC_DEBUG
2755   printf("(%x,%x) Start flush phase\n", udn_tile_coord_x(), 
2756              udn_tile_coord_y());
2757 #endif
2758   flush(stackptr);
2759 #ifdef RAWPATH // TODO GC_DEBUG
2760   printf("(%x,%x) Finish flush phase\n", udn_tile_coord_x(),
2761              udn_tile_coord_y());
2762 #endif
2763
2764   while(true) {
2765     if(FINISHPHASE == gcphase) {
2766       break;
2767     }
2768   }
2769 #ifdef RAWPATH // TODO GC_DEBUG
2770   printf("(%x,%x) Finish gc!\n", udn_tile_coord_x(), udn_tile_coord_y());
2771 #endif
2772 } // void gc_collect(struct garbagelist * stackptr)
2773
2774 inline void gc_nocollect(struct garbagelist * stackptr) {
2775   while(true) {
2776     if(INITPHASE == gcphase) {
2777       break;
2778     }
2779   }
2780 #ifdef RAWPATH // TODO GC_DEBUG
2781   printf("(%x,%x) Do initGC\n", udn_tile_coord_x(), udn_tile_coord_y());
2782 #endif
2783   initGC();
2784   //send init finish msg to core coordinator
2785   send_msg_2(STARTUPCORE, GCFINISHINIT, BAMBOO_NUM_OF_CORE, false);
2786   while(true) {
2787     if(MARKPHASE == gcphase) {
2788       break;
2789     }
2790   }
2791 #ifdef RAWPATH // TODO GC_DEBUG
2792   printf("(%x,%x) Start mark phase\n", udn_tile_coord_x(), 
2793              udn_tile_coord_y());
2794 #endif
2795   mark(true, stackptr);
2796 #ifdef RAWPATH // TODO GC_DEBUG
2797   printf("(%x,%x) Finish mark phase, wait for flush\n", 
2798              udn_tile_coord_x(), udn_tile_coord_y());
2799 #endif
2800   // non-gc core collector routine
2801   while(true) {
2802     if(FLUSHPHASE == gcphase) {
2803       break;
2804     }
2805   }
2806 #ifdef RAWPATH // TODO GC_DEBUG
2807   printf("(%x,%x) Start flush phase\n", udn_tile_coord_x(), 
2808              udn_tile_coord_y());
2809 #endif
2810   flush(stackptr);
2811 #ifdef RAWPATH // TODO GC_DEBUG
2812   printf("(%x,%x) Finish flush phase\n", udn_tile_coord_x(), 
2813              udn_tile_coord_y());
2814 #endif
2815
2816   while(true) {
2817     if(FINISHPHASE == gcphase) {
2818       break;
2819     }
2820   }
2821 #ifdef RAWPATH // TODO GC_DEBUG
2822   printf("(%x,%x) Finish gc!\n", udn_tile_coord_x(), udn_tile_coord_y());
2823 #endif
2824 } // void gc_collect(struct garbagelist * stackptr)
2825
2826 inline void gc(struct garbagelist * stackptr) {
2827   // check if do gc
2828   if(!gcflag) {
2829     gcprocessing = false;
2830     return;
2831   }
2832
2833   // core coordinator routine
2834   if(0 == BAMBOO_NUM_OF_CORE) {
2835 #ifdef GC_DEBUG
2836     printf("(%x,%X) Check if can do gc or not\n", udn_tile_coord_x(),
2837                    udn_tile_coord_y());
2838 #endif
2839     if(!preGC()) {
2840       // not ready to do gc
2841       gcflag = true;
2842       return;
2843     }
2844
2845 #ifdef GC_PROFILE
2846     gc_profileStart();
2847 #endif
2848
2849 #ifdef RAWPATH // TODO GC_DEBUG
2850     printf("(%x,%x) start gc! \n", udn_tile_coord_x(), udn_tile_coord_y());
2851     //dumpSMem();
2852 #endif
2853     gcprocessing = true;
2854     gcphase = INITPHASE;
2855     int i = 0;
2856     waitconfirm = false;
2857     numconfirm = 0;
2858     initGC();
2859
2860     // Note: all cores need to init gc including non-gc cores
2861     for(i = 1; i < NUMCORESACTIVE /*NUMCORES4GC*/; i++) {
2862       // send GC init messages to all cores
2863       send_msg_1(i, GCSTARTINIT, false);
2864     }
2865     bool isfirst = true;
2866     bool allStall = false;
2867
2868 #ifdef RAWPATH // TODO GC_DEBUG
2869     printf("(%x,%x) Check core status \n", udn_tile_coord_x(), 
2870                    udn_tile_coord_y());
2871 #endif
2872
2873     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
2874     while(true) {
2875       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2876       if(gc_checkAllCoreStatus_I()) {
2877         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2878         break;
2879       }
2880       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2881     }
2882 #ifdef GC_PROFILE
2883     gc_profileItem();
2884 #endif
2885 #ifdef RAWPATH // TODO GC_DEBUG
2886     printf("(%x,%x) Start mark phase \n", udn_tile_coord_x(), 
2887                    udn_tile_coord_y());
2888 #endif
2889     // all cores have finished compacting
2890     // restore the gcstatus of all cores
2891     // Note: all cores have to do mark including non-gc cores
2892     gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
2893     for(i = 1; i < NUMCORESACTIVE /*NUMCORES4GC*/; ++i) {
2894       gccorestatus[i] = 1;
2895       // send GC start messages to all cores
2896       send_msg_1(i, GCSTART, false);
2897     }
2898
2899     gcphase = MARKPHASE;
2900     // mark phase
2901     while(MARKPHASE == gcphase) {
2902       mark(isfirst, stackptr);
2903       if(isfirst) {
2904         isfirst = false;
2905       }
2906
2907       // check gcstatus
2908       checkMarkStatue();
2909     }              // while(MARKPHASE == gcphase)
2910                    // send msgs to all cores requiring large objs info
2911                    // Note: only need to ask gc cores, non-gc cores do not host any objs
2912     numconfirm = NUMCORES4GC - 1;
2913     for(i = 1; i < NUMCORES4GC; ++i) {
2914       send_msg_1(i, GCLOBJREQUEST, false);
2915     }
2916     gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
2917     while(true) {
2918       if(numconfirm==0) {
2919         break;
2920       }
2921     }             // wait for responses
2922                   // check the heaptop
2923     if(gcheaptop < gcmarkedptrbound) {
2924       gcheaptop = gcmarkedptrbound;
2925     }
2926 #ifdef GC_PROFILE
2927     gc_profileItem();
2928     // TODO
2929     /*if(BAMBOO_NUM_OF_CORE == 0) {
2930       BAMBOO_DEBUGPRINT(0xeeee);
2931       BAMBOO_DEBUGPRINT_REG(num_markrequest);
2932       BAMBOO_DEBUGPRINT_REG(marktime);
2933     }*/
2934 #endif
2935 #ifdef RAWPATH // TODO GC_DEBUG
2936     printf("(%x,%x) prepare to cache large objs \n", udn_tile_coord_x(),
2937                    udn_tile_coord_y());
2938     //dumpSMem();
2939 #endif
2940     // cache all large objs
2941     if(!cacheLObjs()) {
2942       // no enough space to cache large objs
2943       BAMBOO_EXIT(0xb107);
2944     }
2945     // predict number of blocks to fill for each core
2946     int tmpheaptop = 0;
2947     int numpbc = loadbalance(&tmpheaptop);
2948     // TODO
2949     numpbc = (BAMBOO_SHARED_MEM_SIZE)/(BAMBOO_SMEM_SIZE);
2950 #ifdef RAWPATH // TODO GC_DEBUG
2951     printf("(%x,%x) mark phase finished \n", udn_tile_coord_x(), 
2952                    udn_tile_coord_y());
2953     //dumpSMem();
2954 #endif
2955     //int tmptopptr = 0;
2956     //BASEPTR(gctopcore, 0, &tmptopptr);
2957     // TODO
2958     //tmptopptr = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE);
2959     tmpheaptop = (BAMBOO_BASE_VA) + (BAMBOO_SHARED_MEM_SIZE);
2960 #ifdef DEBUG
2961     BAMBOO_DEBUGPRINT(0xabab);
2962     BAMBOO_DEBUGPRINT_REG(tmptopptr);
2963 #endif
2964     for(i = 0; i < NUMCORES4GC; ++i) {
2965       int tmpcoreptr = 0;
2966       BASEPTR(i, numpbc, &tmpcoreptr);
2967       //send start compact messages to all cores
2968       //TODO bug here, do not know if the direction is positive or negtive?
2969       if (tmpcoreptr < tmpheaptop /*tmptopptr*/) {
2970         gcstopblock[i] = numpbc + 1;
2971         if(i != STARTUPCORE) {
2972           send_msg_2(i, GCSTARTCOMPACT, numpbc+1, false);
2973         } else {
2974           gcblock2fill = numpbc+1;
2975         }                         // if(i != STARTUPCORE)
2976       } else {
2977         gcstopblock[i] = numpbc;
2978         if(i != STARTUPCORE) {
2979           send_msg_2(i, GCSTARTCOMPACT, numpbc, false);
2980         } else {
2981           gcblock2fill = numpbc;
2982         }                         // if(i != STARTUPCORE)
2983       }
2984 #ifdef DEBUG
2985       BAMBOO_DEBUGPRINT(0xf000+i);
2986       BAMBOO_DEBUGPRINT_REG(tmpcoreptr);
2987       BAMBOO_DEBUGPRINT_REG(gcstopblock[i]);
2988 #endif
2989       // init some data strutures for compact phase
2990       gcloads[i] = 0;
2991       gcfilledblocks[i] = 0;
2992       gcrequiredmems[i] = 0;
2993     }
2994
2995 #ifdef GC_PROFILE
2996     gc_profileItem();
2997 #endif
2998
2999     // compact phase
3000     bool finalcompact = false;
3001     // initialize pointers for comapcting
3002     struct moveHelper * orig =
3003       (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
3004     struct moveHelper * to =
3005       (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
3006     initOrig_Dst(orig, to);
3007     int filledblocks = 0;
3008     INTPTR heaptopptr = 0;
3009     bool finishcompact = false;
3010     bool iscontinue = true;
3011     bool localcompact = true;
3012     while((COMPACTPHASE == gcphase) || (SUBTLECOMPACTPHASE == gcphase)) {
3013       if((!finishcompact) && iscontinue) {
3014 #ifdef DEBUG
3015         BAMBOO_DEBUGPRINT(0xe001);
3016         BAMBOO_DEBUGPRINT_REG(numpbc);
3017         BAMBOO_DEBUGPRINT_REG(gcblock2fill);
3018 #endif
3019         finishcompact = compacthelper(orig, to, &filledblocks,
3020                                       &heaptopptr, &localcompact);
3021 #ifdef DEBUG
3022         BAMBOO_DEBUGPRINT(0xe002);
3023         BAMBOO_DEBUGPRINT_REG(finishcompact);
3024         BAMBOO_DEBUGPRINT_REG(gctomove);
3025         BAMBOO_DEBUGPRINT_REG(gcrequiredmems[0]);
3026         BAMBOO_DEBUGPRINT_REG(gcfilledblocks[0]);
3027         BAMBOO_DEBUGPRINT_REG(gcstopblock[0]);
3028 #endif
3029       }
3030
3031       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
3032       if(gc_checkCoreStatus_I()) {
3033         // all cores have finished compacting
3034         // restore the gcstatus of all cores
3035         for(i = 0; i < NUMCORES4GC; ++i) {
3036           gccorestatus[i] = 1;
3037         }
3038         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3039         break;
3040       } else {
3041         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3042         // check if there are spare mem for pending move requires
3043         if(COMPACTPHASE == gcphase) {
3044 #ifdef DEBUG
3045           BAMBOO_DEBUGPRINT(0xe003);
3046 #endif
3047           resolvePendingMoveRequest();
3048 #ifdef DEBUG
3049           BAMBOO_DEBUGPRINT_REG(gctomove);
3050 #endif
3051         } else {
3052 #ifdef DEBUG
3053           BAMBOO_DEBUGPRINT(0xe004);
3054 #endif
3055           compact2Heaptop();
3056         }
3057       }                   // if(gc_checkCoreStatus_I()) else ...
3058
3059       if(gctomove) {
3060 #ifdef DEBUG
3061         BAMBOO_DEBUGPRINT(0xe005);
3062         BAMBOO_DEBUGPRINT_REG(gcmovestartaddr);
3063         BAMBOO_DEBUGPRINT_REG(gcblock2fill);
3064         BAMBOO_DEBUGPRINT_REG(gctomove);
3065 #endif
3066         to->ptr = gcmovestartaddr;
3067         to->numblocks = gcblock2fill - 1;
3068         to->bound = (to->numblocks==0) ?
3069                     BAMBOO_SMEM_SIZE_L :
3070                     BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
3071         BASEPTR(gcdstcore, to->numblocks, &(to->base));
3072         to->offset = to->ptr - to->base;
3073         to->top = (to->numblocks==0) ?
3074                   (to->offset) : (to->bound-BAMBOO_SMEM_SIZE+to->offset);
3075         to->base = to->ptr;
3076         to->offset = BAMBOO_CACHE_LINE_SIZE;
3077         to->ptr += to->offset;                         // for header
3078         to->top += to->offset;
3079         if(gcdstcore == BAMBOO_NUM_OF_CORE) {
3080           localcompact = true;
3081         } else {
3082           localcompact = false;
3083         }
3084         gctomove = false;
3085         iscontinue = true;
3086       } else if(!finishcompact) {
3087         // still pending
3088         iscontinue = false;
3089       }                   // if(gctomove)
3090
3091     }             // while(COMPACTPHASE == gcphase)
3092 #ifdef GC_PROFILE
3093     gc_profileItem();
3094 #endif
3095 #ifdef RAWPATH // TODO GC_DEBUG
3096     printf("(%x,%x) prepare to move large objs \n", udn_tile_coord_x(),
3097                udn_tile_coord_y());
3098     //dumpSMem();
3099 #endif
3100     // move largeObjs
3101     moveLObjs();
3102 #ifdef RAWPATH // TODO GC_DEBUG
3103     printf("(%x,%x) compact phase finished \n", udn_tile_coord_x(), 
3104                    udn_tile_coord_y());
3105     //dumpSMem();
3106 #endif
3107     RUNFREE(orig);
3108     RUNFREE(to);
3109     orig = to = NULL;
3110
3111         gcphase = MAPPHASE;
3112         gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
3113     // Note: all cores should flush their runtime data including non-gc
3114     //       cores
3115     for(i = 1; i < NUMCORES4GC; ++i) {
3116       // send start flush messages to all cores
3117       gccorestatus[i] = 1;
3118       send_msg_1(i, GCSTARTMAPINFO, false);
3119     }
3120 #ifdef GC_PROFILE
3121         gc_profileItem();
3122 #endif
3123 #ifdef RAWPATH // TODO GC_DEBUG
3124     printf("(%x,%x) Start map phase \n", udn_tile_coord_x(), 
3125                    udn_tile_coord_y());
3126 #endif
3127     // mapinto phase
3128     transmappinginfo();
3129 #ifdef RAWPATH // TODO GC_DEBUG
3130     printf("(%x,%x) Finish map phase \n", udn_tile_coord_x(), 
3131                    udn_tile_coord_y());
3132 #endif
3133     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
3134     while(MAPPHASE == gcphase) {
3135       // check the status of all cores
3136       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
3137       if(gc_checkCoreStatus_I()) {
3138                 // all cores have finished sending mapping info 
3139         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3140         break;
3141       }
3142       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3143     }  // while(MAPPHASE == gcphase)
3144
3145     gcphase = FLUSHPHASE;
3146     gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
3147     // Note: all cores should flush their runtime data including non-gc
3148     //       cores
3149     for(i = 1; i < NUMCORESACTIVE /*NUMCORES4GC*/; ++i) {
3150       // send start flush messages to all cores
3151       gccorestatus[i] = 1;
3152       send_msg_1(i, GCSTARTFLUSH, false);
3153     }
3154 #ifdef GC_PROFILE
3155     gc_profileItem();
3156 #endif
3157 #ifdef RAWPATH // TODO GC_DEBUG
3158     printf("(%x,%x) Start flush phase \n", udn_tile_coord_x(), 
3159                    udn_tile_coord_y());
3160 #endif
3161     // flush phase
3162     flush(stackptr);
3163     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
3164     while(FLUSHPHASE == gcphase) {
3165       // check the status of all cores
3166       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
3167       if(gc_checkAllCoreStatus_I()) {
3168         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3169         break;
3170       }
3171       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3172     }             // while(FLUSHPHASE == gcphase)
3173     gcphase = FINISHPHASE;
3174
3175     // invalidate all shared mem pointers
3176     // put it here as it takes time to inform all the other cores to
3177     // finish gc and it might cause problem when some core resumes
3178     // mutator earlier than the other cores
3179     bamboo_cur_msp = NULL;
3180     bamboo_smem_size = 0;
3181     gcflag = false;
3182     gcprocessing = false;
3183
3184 #ifdef GC_PROFILE
3185     gc_profileEnd();
3186 #endif
3187     gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
3188     for(i = 1; i < NUMCORESACTIVE /*NUMCORES4GC*/; ++i) {
3189       // send gc finish messages to all cores
3190       send_msg_1(i, GCFINISH, false);
3191       gccorestatus[i] = 1;
3192     }
3193 #ifdef RAWPATH // TODO GC_DEBUG
3194     printf("(%x,%x) gc finished \n", udn_tile_coord_x(), 
3195                    udn_tile_coord_y());
3196     //dumpSMem();
3197 #endif
3198   } else if(BAMBOO_NUM_OF_CORE < NUMCORES4GC) {
3199     gcprocessing = true;
3200     gc_collect(stackptr);
3201
3202     // invalidate all shared mem pointers
3203     bamboo_cur_msp = NULL;
3204     bamboo_smem_size = 0;
3205
3206     gcflag = false;
3207     gcprocessing = false;
3208   } else {
3209     // not a gc core, should wait for gcfinish msg
3210     gcprocessing = true;
3211     gc_nocollect(stackptr);
3212
3213     // invalidate all shared mem pointers
3214     bamboo_cur_msp = NULL;
3215     bamboo_smem_size = 0;
3216
3217     gcflag = false;
3218     gcprocessing = false;
3219   }
3220 } // void gc(struct garbagelist * stackptr)
3221
3222 #ifdef GC_PROFILE
3223 inline void gc_profileStart(void) {
3224   if(!gc_infoOverflow) {
3225     GCInfo* gcInfo = RUNMALLOC(sizeof(struct gc_info));
3226     gc_infoArray[gc_infoIndex] = gcInfo;
3227     gcInfo->index = 1;
3228     gcInfo->time[0] = BAMBOO_GET_EXE_TIME();
3229   }
3230 }
3231
3232 inline void gc_profileItem(void) {
3233   if(!gc_infoOverflow) {
3234     GCInfo* gcInfo = gc_infoArray[gc_infoIndex];
3235     gcInfo->time[gcInfo->index++] = BAMBOO_GET_EXE_TIME();
3236   }
3237 }
3238
3239 inline void gc_profileEnd(void) {
3240   if(!gc_infoOverflow) {
3241     GCInfo* gcInfo = gc_infoArray[gc_infoIndex];
3242     gcInfo->time[gcInfo->index++] = BAMBOO_GET_EXE_TIME();
3243     gc_infoIndex++;
3244     if(gc_infoIndex == GCINFOLENGTH) {
3245       gc_infoOverflow = true;
3246       //taskInfoIndex = 0;
3247     }
3248   }
3249 }
3250
3251 // output the profiling data
3252 void gc_outputProfileData() {
3253 #ifdef USEIO
3254   int i,j;
3255   unsigned long long totalgc = 0;
3256
3257   //printf("Start Time, End Time, Duration\n");
3258   // output task related info
3259   for(i = 0; i < gc_infoIndex; i++) {
3260     GCInfo * gcInfo = gc_infoArray[i];
3261     unsigned long long tmp = 0;
3262     for(j = 0; j < gcInfo->index; j++) {
3263       printf("%lld(%lld), ", gcInfo->time[j], (gcInfo->time[j]-tmp));
3264       tmp = gcInfo->time[j];
3265     }
3266     tmp = (tmp-gcInfo->time[0]);
3267     printf(" ++ %lld \n", tmp);
3268     totalgc += tmp;
3269   }
3270
3271   if(gc_infoOverflow) {
3272     printf("Caution: gc info overflow!\n");
3273   }
3274
3275   printf("\n\n total gc time: %lld \n", totalgc);
3276 #else
3277   int i = 0;
3278   int j = 0;
3279   unsigned long long totalgc = 0;
3280
3281   BAMBOO_DEBUGPRINT(0xdddd);
3282   // output task related info
3283   for(i= 0; i < gc_infoIndex; i++) {
3284     GCInfo * gcInfo = gc_infoArray[i];
3285     unsigned long long tmp = 0;
3286     BAMBOO_DEBUGPRINT(0xddda);
3287     for(j = 0; j < gcInfo->index; j++) {
3288       BAMBOO_DEBUGPRINT(gcInfo->time[j]);
3289       BAMBOO_DEBUGPRINT(gcInfo->time[j]-tmp);
3290       BAMBOO_DEBUGPRINT(0xdddb);
3291       tmp = gcInfo->time[j];
3292     }
3293     tmp = (tmp-gcInfo->time[0]);
3294     BAMBOO_DEBUGPRINT_REG(tmp);
3295     BAMBOO_DEBUGPRINT(0xdddc);
3296     totalgc += tmp;
3297   }
3298   BAMBOO_DEBUGPRINT(0xdddd);
3299   BAMBOO_DEBUGPRINT_REG(totalgc);
3300
3301   if(gc_infoOverflow) {
3302     BAMBOO_DEBUGPRINT(0xefee);
3303   }
3304
3305   BAMBOO_DEBUGPRINT(0xeeee);
3306 #endif
3307 }
3308 #endif  // #ifdef GC_PROFILE
3309
3310 #endif