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