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