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