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