Enable 1,2,4,8,16,32,50 cores' execution
[IRC.git] / Robust / src / Runtime / bamboo / multicoregarbage.c
1 // BAMBOO_EXIT(0xb000);
2 #ifdef MULTICORE_GC
3 #include "runtime.h"
4 #include "multicoregarbage.h"
5 #include "multicoreruntime.h"
6 #include "runtime_arch.h"
7 #include "SimpleHash.h"
8 #include "GenericHashtable.h"
9 #include "ObjectHash.h"
10 #include "GCSharedHash.h"
11
12 extern int corenum;
13 #ifdef TASK
14 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
15 extern int numqueues[][NUMCLASSES];
16 extern struct genhashtable * activetasks;
17 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
18 extern struct taskparamdescriptor *currtpd;
19 extern struct LockValue runtime_locks[MAXTASKPARAMS];
20 extern int runtime_locklen;
21 #endif
22
23 extern struct global_defs_t * global_defs_p;
24
25 #ifdef SMEMM
26 extern unsigned int gcmem_mixed_threshold;
27 extern unsigned int gcmem_mixed_usedmem;
28 #endif
29
30 #ifdef MGC
31 extern unsigned int bamboo_threadlocks;
32 #endif
33
34 //int gcmarkwaitcounter = -1;
35
36 struct pointerblock {
37   void * ptrs[NUMPTRS];
38   struct pointerblock *next;
39 };
40
41 struct pointerblock *gchead=NULL;
42 int gcheadindex=0;
43 struct pointerblock *gctail=NULL;
44 int gctailindex=0;
45 struct pointerblock *gctail2=NULL;
46 int gctailindex2=0;
47 struct pointerblock *gcspare=NULL;
48
49 #define NUMLOBJPTRS 20
50
51 struct lobjpointerblock {
52   void * lobjs[NUMLOBJPTRS];
53   int lengths[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_CACHE_ADAPT
68 typedef struct gc_cache_revise_info {
69   int orig_page_start_va;
70   int orig_page_end_va;
71   int orig_page_index;
72   int to_page_start_va;
73   int to_page_end_va;
74   int to_page_index;
75   unsigned int revised_sampling[NUMCORESACTIVE];
76 } gc_cache_revise_info_t;
77 gc_cache_revise_info_t gc_cache_revise_infomation;
78 #endif// GC_CACHE_ADAPT
79
80 #ifdef GC_DEBUG
81 // dump whole mem in blocks
82 inline void dumpSMem() {
83   int block = 0;
84   int sblock = 0;
85   unsigned int j = 0;
86   unsigned int i = 0;
87   int coren = 0;
88   int x = 0;
89   int y = 0;
90   printf("(%x,%x) Dump shared mem: \n", udn_tile_coord_x(), 
91              udn_tile_coord_y());
92   // reserved blocks for sblocktbl
93   printf("(%x,%x) ++++ reserved sblocks ++++ \n", udn_tile_coord_x(), 
94              udn_tile_coord_y());
95   for(i=BAMBOO_BASE_VA; i<gcbaseva; i+= 4*16) {
96     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",
97                    udn_tile_coord_x(), udn_tile_coord_y(),
98            *((int *)(i)), *((int *)(i + 4)),
99            *((int *)(i + 4*2)), *((int *)(i + 4*3)),
100            *((int *)(i + 4*4)), *((int *)(i + 4*5)),
101            *((int *)(i + 4*6)), *((int *)(i + 4*7)),
102            *((int *)(i + 4*8)), *((int *)(i + 4*9)),
103            *((int *)(i + 4*10)), *((int *)(i + 4*11)),
104            *((int *)(i + 4*12)), *((int *)(i + 4*13)),
105            *((int *)(i + 4*14)), *((int *)(i + 4*15)));
106   }
107   sblock = gcreservedsb;
108   bool advanceblock = false;
109   // remaining memory
110   for(i=gcbaseva; i<gcbaseva+BAMBOO_SHARED_MEM_SIZE; i+=4*16) {
111     advanceblock = false;
112     // computing sblock # and block #, core coordinate (x,y) also
113     if(j%((BAMBOO_SMEM_SIZE)/(4*16)) == 0) {
114       // finished a sblock
115       if(j < ((BAMBOO_LARGE_SMEM_BOUND)/(4*16))) {
116                 if((j > 0) && (j%((BAMBOO_SMEM_SIZE_L)/(4*16)) == 0)) {
117                   // finished a block
118                   block++;
119                   advanceblock = true;
120                 }
121       } else {
122                 // finished a block
123                 block++;
124                 advanceblock = true;
125       }
126       // compute core #
127       if(advanceblock) {
128                 coren = gc_block2core[block%(NUMCORES4GC*2)];
129       }
130       // compute core coordinate
131       BAMBOO_COORDS(coren, &x, &y);
132       printf("(%x,%x) ==== %d, %d : core (%d,%d), saddr %x====\n",
133                      udn_tile_coord_x(), udn_tile_coord_y(),
134              block, sblock++, x, y,
135              (sblock-1)*(BAMBOO_SMEM_SIZE)+gcbaseva);
136     }
137     j++;
138     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",
139                    udn_tile_coord_x(), udn_tile_coord_y(),
140            *((int *)(i)), *((int *)(i + 4)),
141            *((int *)(i + 4*2)), *((int *)(i + 4*3)),
142            *((int *)(i + 4*4)), *((int *)(i + 4*5)),
143            *((int *)(i + 4*6)), *((int *)(i + 4*7)),
144            *((int *)(i + 4*8)), *((int *)(i + 4*9)),
145            *((int *)(i + 4*10)), *((int *)(i + 4*11)),
146            *((int *)(i + 4*12)), *((int *)(i + 4*13)),
147            *((int *)(i + 4*14)), *((int *)(i + 4*15)));
148   }
149   printf("(%x,%x) \n", udn_tile_coord_x(), udn_tile_coord_y());
150 }
151 #endif
152
153 // should be invoked with interruption closed
154 inline void gc_enqueue_I(void *ptr) {
155   GC_BAMBOO_DEBUGPRINT(0xe601);
156   GC_BAMBOO_DEBUGPRINT_REG(ptr);
157   if (gcheadindex==NUMPTRS) {
158     struct pointerblock * tmp;
159     if (gcspare!=NULL) {
160       tmp=gcspare;
161       gcspare=NULL;
162     } else {
163       tmp=RUNMALLOC_I(sizeof(struct pointerblock));
164     }  // if (gcspare!=NULL)
165     gchead->next=tmp;
166     gchead=tmp;
167     gcheadindex=0;
168   } // if (gcheadindex==NUMPTRS)
169   gchead->ptrs[gcheadindex++]=ptr;
170   GC_BAMBOO_DEBUGPRINT(0xe602);
171 } // void gc_enqueue_I(void *ptr)
172
173 // dequeue and destroy the queue
174 inline void * gc_dequeue_I() {
175   if (gctailindex==NUMPTRS) {
176     struct pointerblock *tmp=gctail;
177     gctail=gctail->next;
178     gctailindex=0;
179     if (gcspare!=NULL) {
180       RUNFREE(tmp);
181     } else {
182       gcspare=tmp;
183     }  // if (gcspare!=NULL)
184   } // if (gctailindex==NUMPTRS)
185   return gctail->ptrs[gctailindex++];
186 } // void * gc_dequeue()
187
188 // dequeue and do not destroy the queue
189 inline void * gc_dequeue2_I() {
190   if (gctailindex2==NUMPTRS) {
191     struct pointerblock *tmp=gctail2;
192     gctail2=gctail2->next;
193     gctailindex2=0;
194   } // if (gctailindex2==NUMPTRS)
195   return gctail2->ptrs[gctailindex2++];
196 } // void * gc_dequeue2()
197
198 inline int gc_moreItems_I() {
199   if ((gchead==gctail)&&(gctailindex==gcheadindex))
200     return 0;
201   return 1;
202 } // int gc_moreItems()
203
204 inline int gc_moreItems2_I() {
205   if ((gchead==gctail2)&&(gctailindex2==gcheadindex))
206     return 0;
207   return 1;
208 } // int gc_moreItems2()
209
210 // should be invoked with interruption closed
211 // enqueue a large obj: start addr & length
212 inline void gc_lobjenqueue_I(void *ptr,
213                              unsigned int length,
214                              unsigned int host) {
215   GC_BAMBOO_DEBUGPRINT(0xe901);
216   if (gclobjheadindex==NUMLOBJPTRS) {
217     struct lobjpointerblock * tmp;
218     if (gclobjspare!=NULL) {
219       tmp=gclobjspare;
220       gclobjspare=NULL;
221     } else {
222       tmp=RUNMALLOC_I(sizeof(struct lobjpointerblock));
223     }  // if (gclobjspare!=NULL)
224     gclobjhead->next=tmp;
225     tmp->prev = gclobjhead;
226     gclobjhead=tmp;
227     gclobjheadindex=0;
228   } // if (gclobjheadindex==NUMLOBJPTRS)
229   gclobjhead->lobjs[gclobjheadindex]=ptr;
230   gclobjhead->lengths[gclobjheadindex]=length;
231   gclobjhead->hosts[gclobjheadindex++]=host;
232   GC_BAMBOO_DEBUGPRINT_REG(gclobjhead->lobjs[gclobjheadindex-1]);
233   GC_BAMBOO_DEBUGPRINT_REG(gclobjhead->lengths[gclobjheadindex-1]);
234   GC_BAMBOO_DEBUGPRINT_REG(gclobjhead->hosts[gclobjheadindex-1]);
235 } // void gc_lobjenqueue_I(void *ptr...)
236
237 // dequeue and destroy the queue
238 inline void * gc_lobjdequeue_I(unsigned int * length,
239                                unsigned int * host) {
240   if (gclobjtailindex==NUMLOBJPTRS) {
241     struct lobjpointerblock *tmp=gclobjtail;
242     gclobjtail=gclobjtail->next;
243     gclobjtailindex=0;
244     gclobjtail->prev = NULL;
245     if (gclobjspare!=NULL) {
246       RUNFREE(tmp);
247     } else {
248       gclobjspare=tmp;
249       tmp->next = NULL;
250       tmp->prev = NULL;
251     }  // if (gclobjspare!=NULL)
252   } // if (gclobjtailindex==NUMLOBJPTRS)
253   if(length != NULL) {
254     *length = gclobjtail->lengths[gclobjtailindex];
255   }
256   if(host != NULL) {
257     *host = (unsigned int)(gclobjtail->hosts[gclobjtailindex]);
258   }
259   return gclobjtail->lobjs[gclobjtailindex++];
260 } // void * gc_lobjdequeue()
261
262 inline int gc_lobjmoreItems_I() {
263   if ((gclobjhead==gclobjtail)&&(gclobjtailindex==gclobjheadindex))
264     return 0;
265   return 1;
266 } // int gc_lobjmoreItems()
267
268 // dequeue and don't destroy the queue
269 inline void gc_lobjdequeue2_I() {
270   if (gclobjtailindex2==NUMLOBJPTRS) {
271     gclobjtail2=gclobjtail2->next;
272     gclobjtailindex2=1;
273   } else {
274     gclobjtailindex2++;
275   }  // if (gclobjtailindex2==NUMLOBJPTRS)
276 } // void * gc_lobjdequeue2()
277
278 inline int gc_lobjmoreItems2_I() {
279   if ((gclobjhead==gclobjtail2)&&(gclobjtailindex2==gclobjheadindex))
280     return 0;
281   return 1;
282 } // int gc_lobjmoreItems2()
283
284 // 'reversly' dequeue and don't destroy the queue
285 inline void gc_lobjdequeue3_I() {
286   if (gclobjtailindex2==0) {
287     gclobjtail2=gclobjtail2->prev;
288     gclobjtailindex2=NUMLOBJPTRS-1;
289   } else {
290     gclobjtailindex2--;
291   }  // if (gclobjtailindex2==NUMLOBJPTRS)
292 } // void * gc_lobjdequeue3()
293
294 inline int gc_lobjmoreItems3_I() {
295   if ((gclobjtail==gclobjtail2)&&(gclobjtailindex2==gclobjtailindex))
296     return 0;
297   return 1;
298 } // int gc_lobjmoreItems3()
299
300 inline void gc_lobjqueueinit4_I() {
301   gclobjtail2 = gclobjtail;
302   gclobjtailindex2 = gclobjtailindex;
303 } // void gc_lobjqueueinit2()
304
305 inline void * gc_lobjdequeue4_I(unsigned int * length,
306                                 unsigned int * host) {
307   if (gclobjtailindex2==NUMLOBJPTRS) {
308     gclobjtail2=gclobjtail2->next;
309     gclobjtailindex2=0;
310   } // if (gclobjtailindex==NUMLOBJPTRS)
311   if(length != NULL) {
312     *length = gclobjtail2->lengths[gclobjtailindex2];
313   }
314   if(host != NULL) {
315     *host = (unsigned int)(gclobjtail2->hosts[gclobjtailindex2]);
316   }
317   return gclobjtail2->lobjs[gclobjtailindex2++];
318 } // void * gc_lobjdequeue()
319
320 inline int gc_lobjmoreItems4_I() {
321   if ((gclobjhead==gclobjtail2)&&(gclobjtailindex2==gclobjheadindex))
322     return 0;
323   return 1;
324 } // int gc_lobjmoreItems(
325
326 unsigned int gccurr_heapbound = 0;
327
328 inline void gettype_size(void * ptr,
329                          int * ttype,
330                          unsigned int * tsize) {
331   int type = ((int *)ptr)[0];
332   unsigned int size = 0;
333   if(type < NUMCLASSES) {
334     // a normal object
335     size = classsize[type];
336   } else {
337     // an array
338     struct ArrayObject *ao=(struct ArrayObject *)ptr;
339     unsigned int elementsize=classsize[type];
340     unsigned int length=ao->___length___;
341     size=sizeof(struct ArrayObject)+length*elementsize;
342   }  // if(type < NUMCLASSES)
343   *ttype = type;
344   *tsize = size;
345 }
346
347 inline bool isLarge(void * ptr,
348                     int * ttype,
349                     unsigned int * tsize) {
350   GC_BAMBOO_DEBUGPRINT(0xe701);
351   GC_BAMBOO_DEBUGPRINT_REG(ptr);
352   // check if a pointer is referring to a large object
353   gettype_size(ptr, ttype, tsize);
354   GC_BAMBOO_DEBUGPRINT(*tsize);
355   unsigned int bound = (BAMBOO_SMEM_SIZE);
356   if(((unsigned int)ptr-gcbaseva) < (BAMBOO_LARGE_SMEM_BOUND)) {
357     bound = (BAMBOO_SMEM_SIZE_L);
358   }
359   if((((unsigned int)ptr-gcbaseva)%(bound))==0) {
360     // ptr is a start of a block
361     GC_BAMBOO_DEBUGPRINT(0xe702);
362     GC_BAMBOO_DEBUGPRINT(1);
363     return true;
364   }
365   if((bound-(((unsigned int)ptr-gcbaseva)%bound)) < (*tsize)) {
366     // it acrosses the boundary of current block
367     GC_BAMBOO_DEBUGPRINT(0xe703);
368     GC_BAMBOO_DEBUGPRINT(1);
369     return true;
370   }
371   GC_BAMBOO_DEBUGPRINT(0);
372   return false;
373 } // bool isLarge(void * ptr, int * ttype, int * tsize)
374
375 inline unsigned int hostcore(void * ptr) {
376   // check the host core of ptr
377   unsigned int host = 0;
378   RESIDECORE(ptr, &host);
379   GC_BAMBOO_DEBUGPRINT(0xedd0);
380   GC_BAMBOO_DEBUGPRINT_REG(ptr);
381   GC_BAMBOO_DEBUGPRINT_REG(host);
382   return host;
383 } // int hostcore(void * ptr)
384
385 inline void cpu2coords(unsigned int coren,
386                            unsigned int * x,
387                                            unsigned int * y) {
388   *x = bamboo_cpu2coords[2*coren];
389   *y = bamboo_cpu2coords[2*coren+1];
390 } // void cpu2coords(...)
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   GC_BAMBOO_DEBUGPRINT(0xee01);
421   int i;
422   if((!waitconfirm) ||
423      (waitconfirm && (numconfirm == 0))) {
424     GC_BAMBOO_DEBUGPRINT(0xee02);
425         unsigned int entry_index = 0;
426         if(waitconfirm) {
427           // phase 2
428           entry_index = (gcnumsrobjs_index == 0) ? 1 : 0;
429         } else {
430           // phase 1
431           entry_index = gcnumsrobjs_index;
432         }
433     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
434     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
435     gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE] = gcself_numsendobjs;
436     gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE] = gcself_numreceiveobjs;
437     // check the status of all cores
438     bool allStall = gc_checkAllCoreStatus_I();
439     GC_BAMBOO_DEBUGPRINT(0xee03);
440     if(allStall) {
441       GC_BAMBOO_DEBUGPRINT(0xee04);
442       // ask for confirm
443       if(!waitconfirm) {
444                 GC_BAMBOO_DEBUGPRINT(0xee05);
445                 // the first time found all cores stall
446                 // send out status confirm msg to all other cores
447                 // reset the corestatus array too
448                 gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
449                 waitconfirm = true;
450                 numconfirm = NUMCORESACTIVE - 1;
451                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
452                 for(i = 1; i < NUMCORESACTIVE; ++i) {
453                   gccorestatus[i] = 1;
454                   // send mark phase finish confirm request msg to core i
455                   send_msg_1(i, GCMARKCONFIRM, false);
456                 }  // for(i = 1; i < NUMCORESACTIVE; ++i)
457       } else {
458                 // Phase 2
459                 // check if the sum of send objs and receive obj are the same
460                 // yes->check if the info is the latest; no->go on executing
461                 unsigned int sumsendobj = 0;
462                 for(i = 0; i < NUMCORESACTIVE; ++i) {
463                   sumsendobj += gcnumsendobjs[gcnumsrobjs_index][i];
464                 }  // for(i = 0; i < NUMCORESACTIVE; ++i)
465                 GC_BAMBOO_DEBUGPRINT(0xee06);
466                 GC_BAMBOO_DEBUGPRINT_REG(sumsendobj);
467                 for(i = 0; i < NUMCORESACTIVE; ++i) {
468                   sumsendobj -= gcnumreceiveobjs[gcnumsrobjs_index][i];
469                 }  // for(i = 0; i < NUMCORESACTIVE; ++i)
470                 GC_BAMBOO_DEBUGPRINT(0xee07);
471                 GC_BAMBOO_DEBUGPRINT_REG(sumsendobj);
472                 if(0 == sumsendobj) {
473                   // Check if there are changes of the numsendobjs or numreceiveobjs on
474                   // each core
475                   bool ischanged = false;
476                   for(i = 0; i < NUMCORESACTIVE; ++i) {
477                         if((gcnumsendobjs[0][i] != gcnumsendobjs[1][i]) || 
478                                 (gcnumreceiveobjs[0][i] != gcnumreceiveobjs[1][i]) ) {
479                           ischanged = true;
480                           break;
481                         }
482                   }  // for(i = 0; i < NUMCORESACTIVE; ++i)
483                   GC_BAMBOO_DEBUGPRINT(0xee08);
484                   GC_BAMBOO_DEBUGPRINT_REG(ischanged);
485                   if(!ischanged) {
486                         GC_BAMBOO_DEBUGPRINT(0xee09);
487                         // all the core status info are the latest
488                         // stop mark phase
489                         gcphase = COMPACTPHASE;
490                         // restore the gcstatus for all cores
491                         for(i = 0; i < NUMCORESACTIVE; ++i) {
492                           gccorestatus[i] = 1;
493                         }  // for(i = 0; i < NUMCORESACTIVE; ++i)
494                   } else {
495                         // There were changes between phase 1 and phase 2, can not decide 
496                         // whether the mark phase has been finished
497                         waitconfirm = false;
498                         // As it fails in phase 2, flip the entries
499                         gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
500                   } // if(!ischanged)
501                 } else {
502                   // There were changes between phase 1 and phase 2, can not decide 
503                   // whether the mark phase has been finished
504                   waitconfirm = false;
505                   // As it fails in phase 2, flip the entries
506                   gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
507                 } // if(0 == sumsendobj) else ...
508                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
509       } // if(!gcwaitconfirm) else()
510     } else {
511           /*if(waitconfirm) {
512                 // There were changes between phase 1 and phase 2, can not decide 
513                 // whether the mark phase has been finished
514                 waitconfirm = false;
515                 // As it fails in phase 2, flip the entries
516                 gcnumsrobjs_index = (gcnumsrobjs_index == 0) ? 1 : 0;
517                 //gcmarkwaitcounter = 1000;
518                 //BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
519           }*/ /*else if(gcmarkwaitcounter == 0) {
520                 tprintf("mark confirm reques \n");
521                 // need to triger status check
522                 gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
523                 waitconfirm = true;
524                 numconfirm = NUMCORESACTIVE - 1;
525                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
526                 for(i = 1; i < NUMCORESACTIVE; ++i) {
527                   gccorestatus[i] = 1;
528                   // send mark phase finish confirm request msg to core i
529                   send_msg_1(i, GCMARKCONFIRM, false);
530                 }  // for(i = 1; i < NUMCORESACTIVE; ++i)
531                 gcmarkwaitcounter = -1;
532           } else if(gcmarkwaitcounter != -1) {
533                 gcmarkwaitcounter--;
534                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
535           }*/
536           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
537     } // if(allStall)
538   }  // if((!waitconfirm)...
539   GC_BAMBOO_DEBUGPRINT(0xee0a);
540 } // void checkMarkStatue()
541
542 inline void initGC() {
543   int i;
544   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
545         //gcmarkwaitcounter = -1;
546     for(i = 0; i < NUMCORES4GC; ++i) {
547       gccorestatus[i] = 1;
548       gcnumsendobjs[0][i] = gcnumsendobjs[1][i] = 0;
549       gcnumreceiveobjs[0][i] = gcnumreceiveobjs[1][i] = 0;
550       gcloads[i] = 0;
551       gcrequiredmems[i] = 0;
552       gcfilledblocks[i] = 0;
553       gcstopblock[i] = 0;
554     } // for(i = 0; i < NUMCORES4GC; ++i)
555     for(i = NUMCORES4GC; i < NUMCORESACTIVE; ++i) {
556       gccorestatus[i] = 1;
557       gcnumsendobjs[0][i] = gcnumsendobjs[1][i] = 0;
558       gcnumreceiveobjs[0][i] = gcnumreceiveobjs[1][i] = 0;
559     }
560     gcheaptop = 0;
561     gctopcore = 0;
562     gctopblock = 0;
563 #ifdef GC_TBL_DEBUG
564         // initialize the gcmappingtbl
565         BAMBOO_MEMSET_WH(gcmappingtbl, 0, bamboo_rmsp_size);
566 #endif
567   } // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
568   gcself_numsendobjs = 0;
569   gcself_numreceiveobjs = 0;
570   gcmarkedptrbound = 0;
571   gcnumlobjs = 0;
572   gcmovestartaddr = 0;
573   gctomove = false;
574   gcblock2fill = 0;
575   gcmovepending = 0;
576   gccurr_heaptop = 0;
577   gcdstcore = 0;
578
579   // initialize queue
580   if (gchead==NULL) {
581     gcheadindex=gctailindex=gctailindex2 = 0;
582     gchead=gctail=gctail2=RUNMALLOC(sizeof(struct pointerblock));
583   } else {
584     gctailindex = gctailindex2 = gcheadindex;
585     gctail = gctail2 = gchead;
586   }
587
588   // initialize the large obj queues
589   if (gclobjhead==NULL) {
590     gclobjheadindex=0;
591     gclobjtailindex=0;
592     gclobjtailindex2 = 0;
593     gclobjhead=gclobjtail=gclobjtail2=
594           RUNMALLOC(sizeof(struct lobjpointerblock));
595   } else {
596     gclobjtailindex = gclobjtailindex2 = gclobjheadindex = 0;
597     gclobjtail = gclobjtail2 = gclobjhead;
598   }
599   gclobjhead->next = gclobjhead->prev = NULL;
600
601   freeMGCHash(gcforwardobjtbl);
602   gcforwardobjtbl = allocateMGCHash(20, 3);
603
604 #ifdef GC_PROFILE
605   gc_num_livespace = 0;
606   gc_num_freespace = 0;
607   gc_num_lobj = 0;
608   gc_num_lobjspace = 0;
609   gc_num_liveobj = 0;
610   gc_num_forwardobj = 0;
611   gc_num_profiles = NUMCORESACTIVE - 1;
612 #endif
613 } // void initGC()
614
615 // compute load balance for all cores
616 inline int loadbalance(unsigned int * heaptop) {
617   // compute load balance
618   int i;
619
620   // get the total loads
621   unsigned int tloads = gcloads[STARTUPCORE];
622   for(i = 1; i < NUMCORES4GC; i++) {
623     tloads += gcloads[i];
624   }
625   *heaptop = gcbaseva + tloads;
626
627   GC_BAMBOO_DEBUGPRINT(0xdddd);
628   GC_BAMBOO_DEBUGPRINT_REG(tloads);
629   GC_BAMBOO_DEBUGPRINT_REG(*heaptop);
630   unsigned int b = 0;
631   BLOCKINDEX(*heaptop, &b);
632   unsigned int numbpc = (unsigned int)b/(unsigned int)(NUMCORES4GC);// num of blocks per core
633   GC_BAMBOO_DEBUGPRINT_REG(b);
634   GC_BAMBOO_DEBUGPRINT_REG(numbpc);
635   gctopblock = b;
636   RESIDECORE(heaptop, &gctopcore);
637   GC_BAMBOO_DEBUGPRINT_REG(gctopcore);
638   return numbpc;
639 } // void loadbalance(int * heaptop)
640
641 inline bool cacheLObjs() {
642   // check the total mem size need for large objs
643   unsigned long long sumsize = 0;
644   unsigned int size = 0;
645   GC_BAMBOO_DEBUGPRINT(0xe801);
646   gclobjtail2 = gclobjtail;
647   gclobjtailindex2 = gclobjtailindex;
648   unsigned int tmp_lobj = 0;
649   unsigned int tmp_len = 0;
650   unsigned int tmp_host = 0;
651   // compute total mem size required and sort the lobjs in ascending order
652   // TODO USE QUICK SORT INSTEAD?
653   while(gc_lobjmoreItems2_I()) {
654     gc_lobjdequeue2_I();
655     tmp_lobj = gclobjtail2->lobjs[gclobjtailindex2-1];
656     tmp_host = gclobjtail2->hosts[gclobjtailindex2-1];
657     tmp_len = gclobjtail2->lengths[gclobjtailindex2 - 1];
658     sumsize += tmp_len;
659 #ifdef GC_PROFILE
660 #ifdef MGC_SPEC
661         if((STARTUPCORE != BAMBOO_NUM_OF_CORE) || gc_profile_flag) {
662 #endif
663         gc_num_lobj++;
664 #ifdef MGC_SPEC
665         }
666 #endif
667 #endif
668     GC_BAMBOO_DEBUGPRINT_REG(gclobjtail2->lobjs[gclobjtailindex2-1]);
669     GC_BAMBOO_DEBUGPRINT_REG(tmp_len);
670     GC_BAMBOO_DEBUGPRINT_REG(sumsize);
671     unsigned int i = gclobjtailindex2-1;
672     struct lobjpointerblock * tmp_block = gclobjtail2;
673     // find the place to insert
674     while(true) {
675       if(i == 0) {
676                 if(tmp_block->prev == NULL) {
677                   break;
678                 }
679                 if(tmp_block->prev->lobjs[NUMLOBJPTRS-1] > tmp_lobj) {
680                   tmp_block->lobjs[i] = tmp_block->prev->lobjs[NUMLOBJPTRS-1];
681                   tmp_block->lengths[i] = tmp_block->prev->lengths[NUMLOBJPTRS-1];
682                   tmp_block->hosts[i] = tmp_block->prev->hosts[NUMLOBJPTRS-1];
683                   tmp_block = tmp_block->prev;
684                   i = NUMLOBJPTRS-1;
685                 } else {
686                   break;
687                 }  // if(tmp_block->prev->lobjs[NUMLOBJPTRS-1] < tmp_lobj)
688           } else {
689                 if(tmp_block->lobjs[i-1] > tmp_lobj) {
690                   tmp_block->lobjs[i] = tmp_block->lobjs[i-1];
691                   tmp_block->lengths[i] = tmp_block->lengths[i-1];
692                   tmp_block->hosts[i] = tmp_block->hosts[i-1];
693                   i--;
694                 } else {
695                   break;
696                 }  // if(tmp_block->lobjs[i-1] < tmp_lobj)
697       }  // if(i ==0 ) else {}
698     }   // while(true)
699     // insert it
700     if(i != gclobjtailindex2 - 1) {
701       tmp_block->lobjs[i] = tmp_lobj;
702       tmp_block->lengths[i] = tmp_len;
703       tmp_block->hosts[i] = tmp_host;
704     }
705   }  // while(gc_lobjmoreItems2())
706
707 #ifdef GC_PROFILE
708 #ifdef MGC_SPEC
709         if((STARTUPCORE != BAMBOO_NUM_OF_CORE) || gc_profile_flag) {
710 #endif
711   gc_num_lobjspace = sumsize;
712 #ifdef MGC_SPEC
713         }
714 #endif
715 #endif
716   // check if there are enough space to cache these large objs
717   unsigned int dst = gcbaseva + (BAMBOO_SHARED_MEM_SIZE) -sumsize;
718   if((unsigned long long)gcheaptop > (unsigned long long)dst) {
719     // do not have enough room to cache large objs
720     GC_BAMBOO_DEBUGPRINT(0xe802);
721     GC_BAMBOO_DEBUGPRINT_REG(dst);
722     GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
723         GC_BAMBOO_DEBUGPRINT_REG(sumsize);
724     return false;
725   }
726   GC_BAMBOO_DEBUGPRINT(0xe803);
727   GC_BAMBOO_DEBUGPRINT_REG(dst);
728   GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
729
730   gcheaptop = dst; // Note: record the start of cached lobjs with gcheaptop
731   // cache the largeObjs to the top of the shared heap
732   dst = gcbaseva + (BAMBOO_SHARED_MEM_SIZE);
733   while(gc_lobjmoreItems3_I()) {
734     gc_lobjdequeue3_I();
735     size = gclobjtail2->lengths[gclobjtailindex2];
736     // set the mark field to , indicating that this obj has been moved
737     // and need to be flushed
738     ((int *)(gclobjtail2->lobjs[gclobjtailindex2]))[BAMBOOMARKBIT] = COMPACTED;
739     dst -= size;
740     if((unsigned int)dst < 
741                 (unsigned int)(gclobjtail2->lobjs[gclobjtailindex2]+size)) {
742       memmove(dst, gclobjtail2->lobjs[gclobjtailindex2], size);
743     } else {
744       memcpy(dst, gclobjtail2->lobjs[gclobjtailindex2], size);
745     }
746     GC_BAMBOO_DEBUGPRINT(0x804);
747     GC_BAMBOO_DEBUGPRINT_REG(gclobjtail2->lobjs[gclobjtailindex2]);
748     GC_BAMBOO_DEBUGPRINT(dst);
749     GC_BAMBOO_DEBUGPRINT_REG(size);
750     GC_BAMBOO_DEBUGPRINT_REG(*((int*)gclobjtail2->lobjs[gclobjtailindex2]));
751     GC_BAMBOO_DEBUGPRINT_REG(*((int*)(dst)));
752   }
753   return true;
754 } // void cacheLObjs()
755
756 // update the bmmboo_smemtbl to record current shared mem usage
757 void updateSmemTbl(unsigned int coren,
758                    unsigned int localtop) {
759   unsigned int ltopcore = 0;
760   unsigned int bound = BAMBOO_SMEM_SIZE_L;
761   BLOCKINDEX(localtop, &ltopcore);
762   if((unsigned int)localtop>=(unsigned int)(gcbaseva+BAMBOO_LARGE_SMEM_BOUND)){
763     bound = BAMBOO_SMEM_SIZE;
764   }
765   unsigned int load = (unsigned int)(localtop-gcbaseva)%(unsigned int)bound;
766   unsigned int i = 0;
767   unsigned int j = 0;
768   unsigned int toset = 0;
769   do {
770     toset = gc_core2block[2*coren+i]+(unsigned int)(NUMCORES4GC*2)*j;
771 #ifdef GC_TBL_DEBUG
772         if(toset >= gcnumblock) {
773           tprintf("ltopcore: %d, localtop: %x, toset: %d, gcnumblock: %d (%d, %d) \n", ltopcore, localtop, toset, gcnumblock, i, j);
774           BAMBOO_EXIT(0xb001);
775         }
776 #endif
777     if(toset < ltopcore) {
778       bamboo_smemtbl[toset]=
779         (toset<NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
780 #ifdef SMEMM
781           gcmem_mixed_usedmem += bamboo_smemtbl[toset];
782 #endif
783     } else if(toset == ltopcore) {
784       bamboo_smemtbl[toset] = load;
785 #ifdef SMEMM
786           gcmem_mixed_usedmem += bamboo_smemtbl[toset];
787 #endif
788       break;
789     } else {
790       break;
791     }
792     i++;
793     if(i == 2) {
794       i = 0;
795       j++;
796     }
797   } while(true);
798 } // void updateSmemTbl(int, int)
799
800 inline void moveLObjs() {
801   GC_BAMBOO_DEBUGPRINT(0xea01);
802 #ifdef SMEMM
803   // update the gcmem_mixed_usedmem
804   gcmem_mixed_usedmem = 0;
805 #endif
806   // zero out the smemtbl
807   BAMBOO_MEMSET_WH(bamboo_smemtbl, 0, sizeof(int)*gcnumblock);
808   // find current heap top
809   // flush all gcloads to indicate the real heap top on one core
810   // previous it represents the next available ptr on a core
811   if(((unsigned int)gcloads[0] > (unsigned int)(gcbaseva+BAMBOO_SMEM_SIZE_L))
812      && (((unsigned int)gcloads[0]%(BAMBOO_SMEM_SIZE)) == 0)) {
813     // edge of a block, check if this is exactly the heaptop
814     BASEPTR(0, gcfilledblocks[0]-1, &(gcloads[0]));
815     gcloads[0]+=(gcfilledblocks[0]>1 ?
816                  (BAMBOO_SMEM_SIZE) : (BAMBOO_SMEM_SIZE_L));
817   }
818   updateSmemTbl(0, gcloads[0]);
819   GC_BAMBOO_DEBUGPRINT(0xea02);
820   GC_BAMBOO_DEBUGPRINT_REG(gcloads[0]);
821   GC_BAMBOO_DEBUGPRINT_REG(bamboo_smemtbl[0]);
822   for(int i = 1; i < NUMCORES4GC; i++) {
823     unsigned int tmptop = 0;
824     GC_BAMBOO_DEBUGPRINT(0xf000+i);
825     GC_BAMBOO_DEBUGPRINT_REG(gcloads[i]);
826     GC_BAMBOO_DEBUGPRINT_REG(gcfilledblocks[i]);
827     if((gcfilledblocks[i] > 0)
828        && (((unsigned int)gcloads[i] % (BAMBOO_SMEM_SIZE)) == 0)) {
829       // edge of a block, check if this is exactly the heaptop
830       BASEPTR(i, gcfilledblocks[i]-1, &gcloads[i]);
831       gcloads[i] += 
832                 (gcfilledblocks[i]>1 ? (BAMBOO_SMEM_SIZE) : (BAMBOO_SMEM_SIZE_L));
833       tmptop = gcloads[i];
834     }
835     updateSmemTbl(i, gcloads[i]);
836     GC_BAMBOO_DEBUGPRINT_REG(gcloads[i]);
837   } // for(int i = 1; i < NUMCORES4GC; i++) {
838
839   // find current heap top
840   // TODO
841   // a bug here: when using local allocation, directly move large objects
842   // to the highest free chunk might not be memory efficient
843   unsigned int tmpheaptop = 0;
844   unsigned int size = 0;
845   unsigned int bound = 0;
846   int i = 0;
847   for(i = gcnumblock-1; i >= 0; i--) {
848     if(bamboo_smemtbl[i] > 0) {
849       break;
850     }
851   }
852   if(i == -1) {
853     tmpheaptop = gcbaseva;
854   } else {
855     tmpheaptop = gcbaseva+bamboo_smemtbl[i]+((i<NUMCORES4GC) ?
856                 (BAMBOO_SMEM_SIZE_L*i) :
857         (BAMBOO_SMEM_SIZE*(i-NUMCORES4GC)+BAMBOO_LARGE_SMEM_BOUND));
858   }
859
860   // move large objs from gcheaptop to tmpheaptop
861   // write the header first
862   unsigned int tomove = gcbaseva+(BAMBOO_SHARED_MEM_SIZE)-gcheaptop;
863 #ifdef SMEMM
864   gcmem_mixed_usedmem += tomove;
865 #endif
866   GC_BAMBOO_DEBUGPRINT(0xea03);
867   GC_BAMBOO_DEBUGPRINT_REG(tomove);
868   GC_BAMBOO_DEBUGPRINT_REG(tmpheaptop);
869   GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
870   // flush the sbstartbl
871   BAMBOO_MEMSET_WH(&(gcsbstarttbl[gcreservedsb]), '\0',
872           (BAMBOO_SHARED_MEM_SIZE/BAMBOO_SMEM_SIZE-(unsigned int)gcreservedsb)
873           *sizeof(unsigned int));
874   if(tomove == 0) {
875     gcheaptop = tmpheaptop;
876   } else {
877     // check how many blocks it acrosses
878     unsigned int remain = tmpheaptop-gcbaseva;
879     unsigned int sb = remain/BAMBOO_SMEM_SIZE+(unsigned int)gcreservedsb;//number of the sblock
880     unsigned int b = 0;  // number of the block
881     BLOCKINDEX(tmpheaptop, &b);
882     // check the remaining space in this block
883     bound = (BAMBOO_SMEM_SIZE);
884     if(remain < (BAMBOO_LARGE_SMEM_BOUND)) {
885       bound = (BAMBOO_SMEM_SIZE_L);
886     }
887     remain = bound - remain%bound;
888
889     GC_BAMBOO_DEBUGPRINT(0xea04);
890     size = 0;
891     unsigned int isize = 0;
892     unsigned int host = 0;
893     unsigned int ptr = 0;
894     unsigned int base = tmpheaptop;
895     unsigned int cpysize = 0;
896     remain -= BAMBOO_CACHE_LINE_SIZE;
897     tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
898     gc_lobjqueueinit4_I();
899     while(gc_lobjmoreItems4_I()) {
900       ptr = (unsigned int)(gc_lobjdequeue4_I(&size, &host));
901       ALIGNSIZE(size, &isize);
902       if(remain < isize) {
903                 // this object acrosses blocks
904                 if(cpysize > 0) {
905                   // close current block, fill its header
906                   BAMBOO_MEMSET_WH(base, '\0', BAMBOO_CACHE_LINE_SIZE);
907                   *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
908                   bamboo_smemtbl[b]+=BAMBOO_CACHE_LINE_SIZE;//add the size of header
909 #ifdef GC_TBL_DEBUG
910                   if(b >= gcnumblock) {
911                         BAMBOO_EXIT(0xb002);
912                   }
913 #endif
914                   cpysize = 0;
915                   base = tmpheaptop;
916                   if(remain == 0) {
917                         remain = ((tmpheaptop-gcbaseva)<(BAMBOO_LARGE_SMEM_BOUND)) ?
918                                          BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
919                   }
920                   remain -= BAMBOO_CACHE_LINE_SIZE;
921                   tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
922                   BLOCKINDEX(tmpheaptop, &b);
923                   sb = (unsigned int)(tmpheaptop-gcbaseva)/(BAMBOO_SMEM_SIZE)
924                         +gcreservedsb;
925                 }  // if(cpysize > 0)
926
927                 // move the large obj
928                 if((unsigned int)gcheaptop < (unsigned int)(tmpheaptop+size)) {
929                   memmove(tmpheaptop, gcheaptop, size);
930                 } else {
931                   //BAMBOO_WRITE_HINT_CACHE(tmpheaptop, size);
932                   memcpy(tmpheaptop, gcheaptop, size);
933                 }
934                 // fill the remaining space with -2 padding
935                 BAMBOO_MEMSET_WH(tmpheaptop+size, -2, isize-size);
936                 GC_BAMBOO_DEBUGPRINT(0xea05);
937                 GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
938                 GC_BAMBOO_DEBUGPRINT_REG(tmpheaptop);
939                 GC_BAMBOO_DEBUGPRINT_REG(size);
940                 GC_BAMBOO_DEBUGPRINT_REG(isize);
941                 GC_BAMBOO_DEBUGPRINT_REG(base);
942                 gcheaptop += size;
943 #ifdef GC_TBL_DEBUG
944                 if((gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)] != 3)) {
945                   tprintf("Error moveLobj: %x %x \n", 
946                           (int)ptr, ((int *)(ptr))[BAMBOOMARKBIT] );
947                   BAMBOO_EXIT(0xb003);
948                 }
949 #endif
950                 // cache the mapping info 
951                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)] = 
952                   (unsigned int)tmpheaptop;
953 #ifdef GC_TBL_DEBUG
954                 if(gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)] == 
955                         gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)-1]) {
956                   tprintf("Error moveobj ^^ : %x, %x, %d \n", (int)ptr, 
957                           (int)tmpheaptop, OBJMAPPINGINDEX((unsigned int)ptr));
958                   BAMBOO_EXIT(0xb004);
959                 }
960 #endif
961                 GC_BAMBOO_DEBUGPRINT(0xcdca);
962                 GC_BAMBOO_DEBUGPRINT_REG(ptr);
963                 GC_BAMBOO_DEBUGPRINT_REG(tmpheaptop);
964                 tmpheaptop += isize;
965
966                 // set the gcsbstarttbl and bamboo_smemtbl
967                 unsigned int tmpsbs=1+(unsigned int)(isize-remain-1)/BAMBOO_SMEM_SIZE;
968                 for(int k = 1; k < tmpsbs; k++) {
969                   gcsbstarttbl[sb+k] = -1;
970 #ifdef GC_TBL_DEBUG
971                   if((sb+k) >= gcsbstarttbl_len) {
972                         BAMBOO_EXIT(0xb005);
973                   }
974 #endif
975                 }
976                 sb += tmpsbs;
977                 bound = (b<NUMCORES4GC) ? BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
978                 BLOCKINDEX(tmpheaptop-1, &tmpsbs);
979                 for(; b < tmpsbs; b++) {
980                   bamboo_smemtbl[b] = bound;
981 #ifdef GC_TBL_DEBUG
982                   if(b >= gcnumblock) {
983                         BAMBOO_EXIT(0xb006);
984                   }
985 #endif
986                   if(b==NUMCORES4GC-1) {
987                         bound = BAMBOO_SMEM_SIZE;
988                   }
989                 }
990                 if(((unsigned int)(isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) {
991                   gcsbstarttbl[sb] = -1;
992                   remain = ((tmpheaptop-gcbaseva)<(BAMBOO_LARGE_SMEM_BOUND)) ?
993                                    BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
994                   bamboo_smemtbl[b] = bound;
995                 } else {
996                   gcsbstarttbl[sb] = (int)tmpheaptop;
997                   remain = tmpheaptop-gcbaseva;
998                   bamboo_smemtbl[b] = remain%bound;
999                   remain = bound - bamboo_smemtbl[b];
1000                 } // if(((isize-remain)%(BAMBOO_SMEM_SIZE)) == 0) else ...
1001 #ifdef GC_TBL_DEBUG
1002                 if(sb >= gcsbstarttbl_len) {
1003                   BAMBOO_EXIT(0xb007);
1004                 }
1005                 if(b >= gcnumblock) {
1006                   BAMBOO_EXIT(0xb008);
1007                 }
1008 #endif
1009
1010                 // close current block and fill the header
1011                 BAMBOO_MEMSET_WH(base, '\0', BAMBOO_CACHE_LINE_SIZE);
1012                 *((int*)base) = isize + BAMBOO_CACHE_LINE_SIZE;
1013                 cpysize = 0;
1014                 base = tmpheaptop;
1015                 if(remain == BAMBOO_CACHE_LINE_SIZE) {
1016                   // fill with 0 in case
1017                   BAMBOO_MEMSET_WH(tmpheaptop, '\0', remain);
1018                 }
1019                 remain -= BAMBOO_CACHE_LINE_SIZE;
1020                 tmpheaptop += BAMBOO_CACHE_LINE_SIZE;
1021       } else {
1022                 remain -= isize;
1023                 // move the large obj
1024                 if((unsigned int)gcheaptop < (unsigned int)(tmpheaptop+size)) {
1025                   memmove(tmpheaptop, gcheaptop, size);
1026                 } else {
1027                   memcpy(tmpheaptop, gcheaptop, size);
1028                 }
1029                 // fill the remaining space with -2 padding
1030                 BAMBOO_MEMSET_WH(tmpheaptop+size, -2, isize-size);
1031                 GC_BAMBOO_DEBUGPRINT(0xea06);
1032                 GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
1033                 GC_BAMBOO_DEBUGPRINT_REG(tmpheaptop);
1034                 GC_BAMBOO_DEBUGPRINT_REG(size);
1035                 GC_BAMBOO_DEBUGPRINT_REG(isize);
1036
1037                 gcheaptop += size;
1038                 cpysize += isize;
1039 #ifdef GC_TBL_DEBUG
1040                 if((gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)] != 3)) {
1041                   tprintf("Error moveLobj: %x %x \n", (int)ptr,
1042                           ((int *)(ptr))[BAMBOOMARKBIT] );
1043                   BAMBOO_EXIT(0xb009);
1044                 }
1045 #endif
1046                 // cache the mapping info
1047                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)] = 
1048                   (unsigned int)tmpheaptop;
1049 #ifdef GC_TBL_DEBUG
1050                 if(gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)] == 
1051                         gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)-1]) {
1052                   tprintf("Error moveobj ?? : %x, %x, %d \n", (int)ptr, 
1053                           (int)tmpheaptop, OBJMAPPINGINDEX((unsigned int)ptr));
1054                   BAMBOO_EXIT(0xb00a);
1055                 }
1056                 if(!ISSHAREDOBJ(tmpheaptop)) {
1057                   tprintf("Error: %x, %x \n", (int)ptr, (int)tmpheaptop);
1058                   BAMBOO_EXIT(0xb00b);
1059                 }
1060 #endif
1061                 GC_BAMBOO_DEBUGPRINT(0xcdcc);
1062                 GC_BAMBOO_DEBUGPRINT_REG(ptr);
1063                 GC_BAMBOO_DEBUGPRINT_REG(tmpheaptop);
1064                 GC_BAMBOO_DEBUGPRINT_REG(*((int*)tmpheaptop));
1065                 tmpheaptop += isize;
1066
1067                 // update bamboo_smemtbl
1068                 bamboo_smemtbl[b] += isize;
1069 #ifdef GC_TBL_DEBUG
1070                 if(b >= gcnumblock) {
1071                   BAMBOO_EXIT(0xb00c);
1072                 }
1073 #endif
1074           }  // if(remain < isize) else ...
1075     }  // while(gc_lobjmoreItems())
1076     if(cpysize > 0) {
1077       // close current block, fill the header
1078       BAMBOO_MEMSET_WH(base, '\0', BAMBOO_CACHE_LINE_SIZE);
1079       *((int*)base) = cpysize + BAMBOO_CACHE_LINE_SIZE;
1080       bamboo_smemtbl[b] += BAMBOO_CACHE_LINE_SIZE;//add the size of the header
1081 #ifdef GC_TBL_DEBUG
1082           if(b >= gcnumblock) {
1083                 BAMBOO_EXIT(0xb00d);
1084           }
1085 #endif
1086     } else {
1087       tmpheaptop -= BAMBOO_CACHE_LINE_SIZE;
1088     }
1089     gcheaptop = tmpheaptop;
1090
1091   } // if(tomove == 0)
1092
1093   GC_BAMBOO_DEBUGPRINT(0xea07);
1094   GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
1095
1096   bamboo_free_block = 0;
1097   unsigned int tbound = 0;
1098   do {
1099     tbound = (bamboo_free_block<NUMCORES4GC) ?
1100              BAMBOO_SMEM_SIZE_L : BAMBOO_SMEM_SIZE;
1101     if(bamboo_smemtbl[bamboo_free_block] == tbound) {
1102       bamboo_free_block++;
1103     } else {
1104       // the first non-full partition
1105       break;
1106     }
1107   } while(true);
1108 #ifdef GC_TBL_DEBUG
1109   if(bamboo_free_block >= gcnumblock) {
1110         BAMBOO_EXIT(0xb00e);
1111   }
1112 #endif
1113
1114 #ifdef GC_PROFILE
1115 #ifdef MGC_SPEC
1116         if((STARTUPCORE != BAMBOO_NUM_OF_CORE) || gc_profile_flag) {
1117 #endif
1118   // check how many live space there are
1119   gc_num_livespace = 0;
1120   for(int tmpi = 0; tmpi < gcnumblock; tmpi++) {
1121         gc_num_livespace += bamboo_smemtbl[tmpi];
1122   }
1123   gc_num_freespace = (BAMBOO_SHARED_MEM_SIZE) - gc_num_livespace;
1124 #ifdef MGC_SPEC
1125         }
1126 #endif
1127 #endif
1128   GC_BAMBOO_DEBUGPRINT(0xea08);
1129   GC_BAMBOO_DEBUGPRINT_REG(gcheaptop);
1130 } // void moveLObjs()
1131
1132 inline void markObj(void * objptr) {
1133   if(objptr == NULL) {
1134     return;
1135   }
1136   if(ISSHAREDOBJ(objptr)) {
1137     unsigned int host = hostcore(objptr);
1138     if(BAMBOO_NUM_OF_CORE == host) {
1139       // on this core
1140       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1141       if(((int *)objptr)[BAMBOOMARKBIT] == INIT) {
1142                 // this is the first time that this object is discovered,
1143                 // set the flag as DISCOVERED
1144                 ((int *)objptr)[BAMBOOMARKBIT] = DISCOVERED;
1145                 BAMBOO_CACHE_FLUSH_LINE(objptr);
1146                 gc_enqueue_I(objptr);
1147 #ifdef GC_TBL_DEBUG
1148                 // for test
1149                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)]=1;
1150 #endif
1151           }
1152       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1153     } else {
1154       GC_BAMBOO_DEBUGPRINT(0xbbbb);
1155       GC_BAMBOO_DEBUGPRINT_REG(host);
1156       GC_BAMBOO_DEBUGPRINT_REG(objptr);
1157       // check if this obj has been forwarded
1158       if(!MGCHashcontains(gcforwardobjtbl, (int)objptr)) {
1159                 // send a msg to host informing that objptr is active
1160                 send_msg_2(host, GCMARKEDOBJ, objptr, false);
1161 #ifdef GC_PROFILE
1162 #ifdef MGC_SPEC
1163         if((STARTUPCORE != BAMBOO_NUM_OF_CORE) || gc_profile_flag) {
1164 #endif
1165                 gc_num_forwardobj++;
1166 #ifdef MGC_SPEC
1167         }
1168 #endif
1169 #endif // GC_PROFILE
1170                 gcself_numsendobjs++;
1171                 MGCHashadd(gcforwardobjtbl, (int)objptr);
1172       }
1173     }
1174   } else {
1175 #ifdef GC_TBL_DEBUG
1176         tprintf("Non shared pointer to be marked %x \n", (int)objptr);
1177         BAMBOO_EXIT(0xb00f);
1178 #endif
1179     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1180     gc_enqueue_I(objptr);
1181     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1182   }  // if(ISSHAREDOBJ(objptr))
1183 } // void markObj(void * objptr)
1184
1185 // enqueue root objs
1186 inline void tomark(struct garbagelist * stackptr) {
1187   if(MARKPHASE != gcphase) {
1188     GC_BAMBOO_DEBUGPRINT_REG(gcphase);
1189     BAMBOO_EXIT(0xb010);
1190   }
1191   gcbusystatus = true;
1192   gcnumlobjs = 0;
1193
1194
1195   int i,j;
1196   // enqueue current stack
1197   while(stackptr!=NULL) {
1198     GC_BAMBOO_DEBUGPRINT(0xe501);
1199     GC_BAMBOO_DEBUGPRINT_REG(stackptr->size);
1200     GC_BAMBOO_DEBUGPRINT_REG(stackptr->next);
1201     GC_BAMBOO_DEBUGPRINT_REG(stackptr->array[0]);
1202     for(i=0; i<stackptr->size; i++) {
1203       if(stackptr->array[i] != NULL) {
1204                 markObj(stackptr->array[i]);
1205       }
1206     }
1207     stackptr=stackptr->next;
1208   }
1209   GC_BAMBOO_DEBUGPRINT(0xe502);
1210
1211   // enqueue static pointers global_defs_p
1212   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1213         struct garbagelist * staticptr=(struct garbagelist *)global_defs_p;
1214         while(staticptr != NULL) {
1215           for(i=0; i<staticptr->size; i++) {
1216                 if(staticptr->array[i] != NULL) {
1217                   markObj(staticptr->array[i]);
1218                 }
1219           }
1220           staticptr = staticptr->next;
1221         }
1222   }
1223   GC_BAMBOO_DEBUGPRINT(0xe503);
1224
1225 #ifdef TASK
1226   // enqueue objectsets
1227   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
1228     for(i=0; i<NUMCLASSES; i++) {
1229       struct parameterwrapper ** queues =
1230         objectqueues[BAMBOO_NUM_OF_CORE][i];
1231       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
1232       for(j = 0; j < length; ++j) {
1233                 struct parameterwrapper * parameter = queues[j];
1234                 struct ObjectHash * set=parameter->objectset;
1235                 struct ObjectNode * ptr=set->listhead;
1236                 while(ptr!=NULL) {
1237                   markObj((void *)ptr->key);
1238                   ptr=ptr->lnext;
1239                 }
1240       }
1241     }
1242   }
1243
1244   // euqueue current task descriptor
1245   if(currtpd != NULL) {
1246     GC_BAMBOO_DEBUGPRINT(0xe504);
1247     for(i=0; i<currtpd->numParameters; i++) {
1248       markObj(currtpd->parameterArray[i]);
1249     }
1250   }
1251
1252   GC_BAMBOO_DEBUGPRINT(0xe505);
1253   // euqueue active tasks
1254   if(activetasks != NULL) {
1255     struct genpointerlist * ptr=activetasks->list;
1256     while(ptr!=NULL) {
1257       struct taskparamdescriptor *tpd=ptr->src;
1258       int i;
1259       for(i=0; i<tpd->numParameters; i++) {
1260                 markObj(tpd->parameterArray[i]);
1261       }
1262       ptr=ptr->inext;
1263     }
1264   }
1265
1266   GC_BAMBOO_DEBUGPRINT(0xe506);
1267   // enqueue cached transferred obj
1268   struct QueueItem * tmpobjptr =  getHead(&objqueue);
1269   while(tmpobjptr != NULL) {
1270     struct transObjInfo * objInfo =
1271       (struct transObjInfo *)(tmpobjptr->objectptr);
1272     markObj(objInfo->objptr);
1273     tmpobjptr = getNextQueueItem(tmpobjptr);
1274   }
1275
1276   GC_BAMBOO_DEBUGPRINT(0xe507);
1277   // enqueue cached objs to be transferred
1278   struct QueueItem * item = getHead(totransobjqueue);
1279   while(item != NULL) {
1280     struct transObjInfo * totransobj =
1281       (struct transObjInfo *)(item->objectptr);
1282     markObj(totransobj->objptr);
1283     item = getNextQueueItem(item);
1284   } // while(item != NULL)
1285
1286   GC_BAMBOO_DEBUGPRINT(0xe508);
1287   // enqueue lock related info
1288   for(i = 0; i < runtime_locklen; ++i) {
1289     markObj((void *)(runtime_locks[i].redirectlock));
1290     if(runtime_locks[i].value != NULL) {
1291       markObj((void *)(runtime_locks[i].value));
1292     }
1293   }
1294   GC_BAMBOO_DEBUGPRINT(0xe509);
1295 #endif 
1296
1297 #ifdef MGC
1298   // enqueue global thread queue
1299   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1300         lockthreadqueue();
1301         unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
1302         if(thread_counter > 0) {
1303           unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
1304           for(i = thread_counter; i > 0; i--) {
1305                 markObj((void *)bamboo_thread_queue[4+start]);
1306                 start = (start+1)&bamboo_max_thread_num_mask;
1307           }
1308         }
1309   }
1310
1311   // enqueue the bamboo_threadlocks
1312   if(bamboo_threadlocks != 0) {
1313         markObj((void *)bamboo_threadlocks);
1314   }
1315
1316   // enqueue the bamboo_current_thread
1317   if(bamboo_current_thread != 0) {
1318         markObj((void *)bamboo_current_thread);
1319   }
1320
1321   GC_BAMBOO_DEBUGPRINT(0xe50a);
1322 #endif
1323 } // void tomark(struct garbagelist * stackptr)
1324
1325 inline void mark(bool isfirst,
1326                  struct garbagelist * stackptr) {
1327   if(BAMBOO_NUM_OF_CORE == 0) GC_BAMBOO_DEBUGPRINT(0xed01);
1328   if(isfirst) {
1329     if(BAMBOO_NUM_OF_CORE == 0) GC_BAMBOO_DEBUGPRINT(0xed02);
1330     // enqueue root objs
1331     tomark(stackptr);
1332     gccurr_heaptop = 0; // record the size of all active objs in this core
1333                         // aligned but does not consider block boundaries
1334     gcmarkedptrbound = 0;
1335   }
1336   if(BAMBOO_NUM_OF_CORE == 0) GC_BAMBOO_DEBUGPRINT(0xed03);
1337   unsigned int isize = 0;
1338   bool checkfield = true;
1339   bool sendStall = false;
1340   // mark phase
1341   while(MARKPHASE == gcphase) {
1342     if(BAMBOO_NUM_OF_CORE == 0) GC_BAMBOO_DEBUGPRINT(0xed04);
1343     while(true) {
1344       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1345       bool hasItems = gc_moreItems2_I();
1346       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1347       GC_BAMBOO_DEBUGPRINT(0xed05);
1348       if(!hasItems) {
1349                 break;
1350       }
1351       sendStall = false;
1352       gcbusystatus = true;
1353       checkfield = true;
1354       void * ptr = gc_dequeue2_I();
1355
1356       GC_BAMBOO_DEBUGPRINT_REG(ptr);
1357       unsigned int size = 0;
1358       unsigned int isize = 0;
1359       unsigned int type = 0;
1360       // check if it is a shared obj
1361       if(ISSHAREDOBJ(ptr)) {
1362                 // a shared obj, check if it is a local obj on this core
1363                 unsigned int host = hostcore(ptr);
1364                 bool islocal = (host == BAMBOO_NUM_OF_CORE);
1365                 if(islocal) {
1366                   bool isnotmarked = (((int *)ptr)[BAMBOOMARKBIT] == DISCOVERED);
1367                   if(isLarge(ptr, &type, &size) && isnotmarked) {
1368                         // ptr is a large object and not marked or enqueued
1369                         GC_BAMBOO_DEBUGPRINT(0xecec);
1370                         GC_BAMBOO_DEBUGPRINT_REG(ptr);
1371                         GC_BAMBOO_DEBUGPRINT_REG(*((int*)ptr));
1372                         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1373                         gc_lobjenqueue_I(ptr, size, BAMBOO_NUM_OF_CORE);
1374                         gcnumlobjs++;
1375                         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1376                         // mark this obj
1377                         ((int *)ptr)[BAMBOOMARKBIT] = MARKED;
1378                         BAMBOO_CACHE_FLUSH_LINE(ptr);
1379 #ifdef GC_TBL_DEBUG
1380                         // for test
1381                         gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)]=3;
1382 #endif
1383                   } else if(isnotmarked) {
1384                         // ptr is an unmarked active object on this core
1385                         ALIGNSIZE(size, &isize);
1386                         gccurr_heaptop += isize;
1387                         GC_BAMBOO_DEBUGPRINT(0xaaaa);
1388                         GC_BAMBOO_DEBUGPRINT_REG(ptr);
1389                         GC_BAMBOO_DEBUGPRINT_REG(isize);
1390                         GC_BAMBOO_DEBUGPRINT(((int *)(ptr))[0]);
1391                         // mark this obj
1392                         ((int *)ptr)[BAMBOOMARKBIT] = MARKED;
1393                         BAMBOO_CACHE_FLUSH_LINE(ptr);
1394 #ifdef GC_TBL_DEBUG
1395                         // for test
1396                         gcmappingtbl[OBJMAPPINGINDEX((unsigned int)ptr)]=2;
1397 #endif
1398                   
1399                         if((unsigned int)(ptr + size) > (unsigned int)gcmarkedptrbound) {
1400                           gcmarkedptrbound = (unsigned int)(ptr + size);
1401                         } // if(ptr + size > gcmarkedptrbound)
1402                   } else {
1403                         // ptr is not an active obj or has been marked
1404                         checkfield = false;
1405                   } // if(isLarge(ptr, &type, &size)) else ...
1406                 } 
1407 #ifdef GC_TBL_DEBUG
1408                 else {
1409                   tprintf("Error mark: %x, %d, %d \n", (int)ptr, BAMBOO_NUM_OF_CORE, 
1410                           hostcore(ptr));
1411                   BAMBOO_EXIT(0xb011);
1412                 }
1413 #endif /* can never reach here
1414                 else {
1415                   // check if this obj has been forwarded
1416                   if(!MGCHashcontains(gcforwardobjtbl, (int)ptr)) {
1417                         // send a msg to host informing that ptr is active
1418                         send_msg_2(host, GCMARKEDOBJ, ptr, false);
1419                         gcself_numsendobjs++;
1420                         MGCHashadd(gcforwardobjtbl, (int)ptr);
1421                   }
1422                         checkfield = false;
1423                 }// if(isLocal(ptr)) else ...*/
1424           }   // if(ISSHAREDOBJ(ptr))
1425       GC_BAMBOO_DEBUGPRINT(0xed06);
1426
1427       if(checkfield) {
1428                 // scan all pointers in ptr
1429                 unsigned int * pointer;
1430                 pointer=pointerarray[type];
1431                 if (pointer==0) {
1432                   /* Array of primitives */
1433                   /* Do nothing */
1434                 } else if (((unsigned int)pointer)==1) {
1435                   /* Array of pointers */
1436                   struct ArrayObject *ao=(struct ArrayObject *) ptr;
1437                   int length=ao->___length___;
1438                   int j;
1439                   for(j=0; j<length; j++) {
1440                         void *objptr =
1441                           ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
1442                         markObj(objptr);
1443                   }
1444                   /* check the ArrayObject struct first*/
1445                   {
1446                         pointer=pointerarray[OBJECTTYPE];
1447                         //handle object class
1448                         unsigned int size=pointer[0];
1449                         int i;
1450                         for(i=1; i<=size; i++) {
1451                           unsigned int offset=pointer[i];
1452                           void * objptr=*((void **)(((char *)ao)+offset));
1453                           markObj(objptr);
1454                         }
1455                   }
1456                 } else {
1457                   unsigned int size=pointer[0];
1458                   int i;
1459                   for(i=1; i<=size; i++) {
1460                         unsigned int offset=pointer[i];
1461                         void * objptr=*((void **)(((char *)ptr)+offset));
1462                         markObj(objptr);
1463                   }
1464                 }     // if (pointer==0) else if ... else ...
1465       }   // if(checkfield)
1466     }     // while(gc_moreItems2())
1467     GC_BAMBOO_DEBUGPRINT(0xed07);
1468         gcbusystatus = false;
1469     // send mark finish msg to core coordinator
1470     if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
1471       GC_BAMBOO_DEBUGPRINT(0xed08);
1472       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
1473       gcnumsendobjs[gcnumsrobjs_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
1474       gcnumreceiveobjs[gcnumsrobjs_index][BAMBOO_NUM_OF_CORE]=
1475                 gcself_numreceiveobjs;
1476       gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
1477     } else {
1478       if(!sendStall) {
1479                 GC_BAMBOO_DEBUGPRINT(0xed09);
1480                 send_msg_4(STARTUPCORE, GCFINISHMARK, BAMBOO_NUM_OF_CORE,
1481                                    gcself_numsendobjs, gcself_numreceiveobjs, false);
1482                 sendStall = true;
1483       }
1484     }  // if(STARTUPCORE == BAMBOO_NUM_OF_CORE) ...
1485     GC_BAMBOO_DEBUGPRINT(0xed0a);
1486
1487     if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
1488       GC_BAMBOO_DEBUGPRINT(0xed0b);
1489       return;
1490     }
1491   } // while(MARKPHASE == gcphase)
1492
1493   BAMBOO_CACHE_MF();
1494 } // mark()
1495
1496 inline void compact2Heaptophelper_I(unsigned int coren,
1497                                     unsigned int* p,
1498                                     unsigned int* numblocks,
1499                                     unsigned int* remain) {
1500   unsigned int b;
1501   unsigned int memneed = gcrequiredmems[coren] + BAMBOO_CACHE_LINE_SIZE;
1502   if(STARTUPCORE == coren) {
1503     gctomove = true;
1504     gcmovestartaddr = *p;
1505     gcdstcore = gctopcore;
1506     gcblock2fill = *numblocks + 1;
1507   } else {
1508     send_msg_4(coren, GCMOVESTART, gctopcore, *p, (*numblocks) + 1, false);
1509   }
1510   GC_BAMBOO_DEBUGPRINT_REG(coren);
1511   GC_BAMBOO_DEBUGPRINT_REG(gctopcore);
1512   GC_BAMBOO_DEBUGPRINT_REG(*p);
1513   GC_BAMBOO_DEBUGPRINT_REG(*numblocks+1);
1514   if(memneed < *remain) {
1515     GC_BAMBOO_DEBUGPRINT(0xd104);
1516     *p = *p + memneed;
1517     gcrequiredmems[coren] = 0;
1518     gcloads[gctopcore] += memneed;
1519     *remain = *remain - memneed;
1520   } else {
1521     GC_BAMBOO_DEBUGPRINT(0xd105);
1522     // next available block
1523     *p = *p + *remain;
1524     gcfilledblocks[gctopcore] += 1;
1525     unsigned int newbase = 0;
1526     BASEPTR(gctopcore, gcfilledblocks[gctopcore], &newbase);
1527     gcloads[gctopcore] = newbase;
1528     gcrequiredmems[coren] -= *remain - BAMBOO_CACHE_LINE_SIZE;
1529     gcstopblock[gctopcore]++;
1530     gctopcore = NEXTTOPCORE(gctopblock);
1531     gctopblock++;
1532     *numblocks = gcstopblock[gctopcore];
1533     *p = gcloads[gctopcore];
1534     BLOCKINDEX(*p, &b);
1535     *remain=(b<NUMCORES4GC) ?
1536              ((BAMBOO_SMEM_SIZE_L)-((*p)%(BAMBOO_SMEM_SIZE_L)))
1537              : ((BAMBOO_SMEM_SIZE)-((*p)%(BAMBOO_SMEM_SIZE)));
1538     GC_BAMBOO_DEBUGPRINT(0xd106);
1539     GC_BAMBOO_DEBUGPRINT_REG(gctopcore);
1540     GC_BAMBOO_DEBUGPRINT_REG(*p);
1541     GC_BAMBOO_DEBUGPRINT_REG(b);
1542     GC_BAMBOO_DEBUGPRINT_REG(*remain);
1543   }  // if(memneed < remain)
1544   gcmovepending--;
1545 } // void compact2Heaptophelper_I(int, int*, int*, int*)
1546
1547 inline void compact2Heaptop() {
1548   // no cores with spare mem and some cores are blocked with pending move
1549   // find the current heap top and make them move to the heap top
1550   unsigned int p;
1551   unsigned int numblocks = gcfilledblocks[gctopcore];
1552   p = gcloads[gctopcore];
1553   unsigned int b;
1554   BLOCKINDEX(p, &b);
1555   unsigned int remain = (b<NUMCORES4GC) ?
1556                ((BAMBOO_SMEM_SIZE_L)-(p%(BAMBOO_SMEM_SIZE_L)))
1557                : ((BAMBOO_SMEM_SIZE)-(p%(BAMBOO_SMEM_SIZE)));
1558   // check if the top core finishes
1559   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1560   if(gccorestatus[gctopcore] != 0) {
1561     GC_BAMBOO_DEBUGPRINT(0xd101);
1562     GC_BAMBOO_DEBUGPRINT_REG(gctopcore);
1563     // let the top core finishes its own work first
1564     compact2Heaptophelper_I(gctopcore, &p, &numblocks, &remain);
1565     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1566     return;
1567   }
1568   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1569
1570   GC_BAMBOO_DEBUGPRINT(0xd102);
1571   GC_BAMBOO_DEBUGPRINT_REG(gctopcore);
1572   GC_BAMBOO_DEBUGPRINT_REG(p);
1573   GC_BAMBOO_DEBUGPRINT_REG(b);
1574   GC_BAMBOO_DEBUGPRINT_REG(remain);
1575   for(int i = 0; i < NUMCORES4GC; i++) {
1576     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1577     if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0)) {
1578       GC_BAMBOO_DEBUGPRINT(0xd103);
1579       compact2Heaptophelper_I(i, &p, &numblocks, &remain);
1580       if(gccorestatus[gctopcore] != 0) {
1581                 GC_BAMBOO_DEBUGPRINT(0xd101);
1582                 GC_BAMBOO_DEBUGPRINT_REG(gctopcore);
1583                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1584                 // the top core is not free now
1585                 return;
1586       }
1587     }  // if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0))
1588     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1589   }   // for(i = 0; i < NUMCORES4GC; i++)
1590   GC_BAMBOO_DEBUGPRINT(0xd106);
1591 } // void compact2Heaptop()
1592
1593 inline void resolvePendingMoveRequest() {
1594   GC_BAMBOO_DEBUGPRINT(0xeb01);
1595   GC_BAMBOO_DEBUGPRINT(0xeeee);
1596   for(int k = 0; k < NUMCORES4GC; k++) {
1597     GC_BAMBOO_DEBUGPRINT(0xf000+k);
1598     GC_BAMBOO_DEBUGPRINT_REG(gccorestatus[k]);
1599     GC_BAMBOO_DEBUGPRINT_REG(gcloads[k]);
1600     GC_BAMBOO_DEBUGPRINT_REG(gcfilledblocks[k]);
1601     GC_BAMBOO_DEBUGPRINT_REG(gcstopblock[k]);
1602   }
1603   GC_BAMBOO_DEBUGPRINT(0xffff);
1604   int i;
1605   int j;
1606   bool nosparemem = true;
1607   bool haspending = false;
1608   bool hasrunning = false;
1609   bool noblock = false;
1610   unsigned int dstcore = 0;       // the core who need spare mem
1611   unsigned int sourcecore = 0;       // the core who has spare mem
1612   for(i = j = 0; (i < NUMCORES4GC) && (j < NUMCORES4GC); ) {
1613     if(nosparemem) {
1614       // check if there are cores with spare mem
1615       if(gccorestatus[i] == 0) {
1616                 // finished working, check if it still have spare mem
1617                 if(gcfilledblocks[i] < gcstopblock[i]) {
1618                   // still have spare mem
1619                   nosparemem = false;
1620                   sourcecore = i;
1621                 }  // if(gcfilledblocks[i] < gcstopblock[i]) else ...
1622       }
1623       i++;
1624     }  // if(nosparemem)
1625     if(!haspending) {
1626       if(gccorestatus[j] != 0) {
1627                 // not finished, check if it has pending move requests
1628                 if((gcfilledblocks[j]==gcstopblock[j])&&(gcrequiredmems[j]>0)) {
1629                   dstcore = j;
1630                   haspending = true;
1631                 } else {
1632                   hasrunning = true;
1633                 }  // if((gcfilledblocks[i] == gcstopblock[i])...) else ...
1634       }  // if(gccorestatus[i] == 0) else ...
1635       j++;
1636     }  // if(!haspending)
1637     if(!nosparemem && haspending) {
1638       // find match
1639       unsigned int tomove = 0;
1640       unsigned int startaddr = 0;
1641       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
1642       gcrequiredmems[dstcore] = assignSpareMem_I(sourcecore,
1643                                                  gcrequiredmems[dstcore],
1644                                                  &tomove,
1645                                                  &startaddr);
1646       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
1647       GC_BAMBOO_DEBUGPRINT(0xeb02);
1648       GC_BAMBOO_DEBUGPRINT_REG(sourcecore);
1649       GC_BAMBOO_DEBUGPRINT_REG(dstcore);
1650       GC_BAMBOO_DEBUGPRINT_REG(startaddr);
1651       GC_BAMBOO_DEBUGPRINT_REG(tomove);
1652       if(STARTUPCORE == dstcore) {
1653                 GC_BAMBOO_DEBUGPRINT(0xeb03);
1654                 gcdstcore = sourcecore;
1655                 gctomove = true;
1656                 gcmovestartaddr = startaddr;
1657                 gcblock2fill = tomove;
1658       } else {
1659                 GC_BAMBOO_DEBUGPRINT(0xeb04);
1660                 send_msg_4(dstcore, GCMOVESTART, sourcecore,
1661                                    startaddr, tomove, false);
1662       }
1663       gcmovepending--;
1664       nosparemem = true;
1665       haspending = false;
1666       noblock = true;
1667     }
1668   }   // for(i = 0; i < NUMCORES4GC; i++)
1669   GC_BAMBOO_DEBUGPRINT(0xcccc);
1670   GC_BAMBOO_DEBUGPRINT_REG(hasrunning);
1671   GC_BAMBOO_DEBUGPRINT_REG(haspending);
1672   GC_BAMBOO_DEBUGPRINT_REG(noblock);
1673
1674   if(!hasrunning && !noblock) {
1675     gcphase = SUBTLECOMPACTPHASE;
1676     compact2Heaptop();
1677   }
1678
1679 } // void resovePendingMoveRequest()
1680
1681 struct moveHelper {
1682   unsigned int numblocks;       // block num for heap
1683   unsigned int base;       // base virtual address of current heap block
1684   unsigned int ptr;       // virtual address of current heap top
1685   unsigned int offset;       // offset in current heap block
1686   unsigned int blockbase;   // virtual address of current small block to check
1687   unsigned int blockbound;     // bound virtual address of current small blcok
1688   unsigned int sblockindex;       // index of the small blocks
1689   unsigned int top;       // real size of current heap block to check
1690   unsigned int bound;       // bound size of current heap block to check
1691 }; // struct moveHelper
1692
1693 // If out of boundary of valid shared memory, return false, else return true
1694 inline bool nextSBlock(struct moveHelper * orig) {
1695   orig->blockbase = orig->blockbound;
1696
1697   bool sbchanged = false;
1698   unsigned int origptr = orig->ptr;
1699   unsigned int blockbase = orig->blockbase;
1700   unsigned int blockbound = orig->blockbound;
1701   unsigned int bound = orig->bound;
1702   GC_BAMBOO_DEBUGPRINT(0xecc0);
1703   GC_BAMBOO_DEBUGPRINT_REG(blockbase);
1704   GC_BAMBOO_DEBUGPRINT_REG(blockbound);
1705   GC_BAMBOO_DEBUGPRINT_REG(bound);
1706   GC_BAMBOO_DEBUGPRINT_REG(origptr);
1707 outernextSBlock:
1708   // check if across a big block
1709   // TODO now do not zero out the whole memory, maybe the last two conditions
1710   // are useless now
1711   if((blockbase>=bound)||(origptr>=bound)
1712           ||((origptr!=NULL)&&(*((int*)origptr))==0)||((*((int*)blockbase))==0)) {
1713 innernextSBlock:
1714     // end of current heap block, jump to next one
1715     orig->numblocks++;
1716     GC_BAMBOO_DEBUGPRINT(0xecc1);
1717     GC_BAMBOO_DEBUGPRINT_REG(orig->numblocks);
1718     BASEPTR(BAMBOO_NUM_OF_CORE, orig->numblocks, &(orig->base));
1719     GC_BAMBOO_DEBUGPRINT(orig->base);
1720     if(orig->base >= gcbaseva + BAMBOO_SHARED_MEM_SIZE) {
1721       // out of boundary
1722       orig->ptr = orig->base; // set current ptr to out of boundary too
1723       return false;
1724     }
1725     orig->blockbase = orig->base;
1726     orig->sblockindex = 
1727           (unsigned int)(orig->blockbase-gcbaseva)/BAMBOO_SMEM_SIZE;
1728     sbchanged = true;
1729     unsigned int blocknum = 0;
1730     BLOCKINDEX(orig->base, &blocknum);
1731     if(bamboo_smemtbl[blocknum] == 0) {
1732 #ifdef GC_TBL_DEBUG
1733           if(blocknum >= gcnumblock) {
1734                 BAMBOO_EXIT(0xb012);
1735           }
1736 #endif
1737       // goto next block
1738       goto innernextSBlock;
1739     }
1740         // check the bamboo_smemtbl to decide the real bound
1741         orig->bound = orig->base + bamboo_smemtbl[blocknum];
1742   } else if(0 == (orig->blockbase%BAMBOO_SMEM_SIZE)) {
1743     orig->sblockindex += 1;
1744     sbchanged = true;
1745   }  // if((orig->blockbase >= orig->bound) || (orig->ptr >= orig->bound)...
1746
1747   // check if this sblock should be skipped or have special start point
1748   int sbstart = gcsbstarttbl[orig->sblockindex];
1749 #ifdef GC_TBL_DEBUG
1750   if((orig->sblockindex) >= gcsbstarttbl_len) {
1751         BAMBOO_EXIT(0xb013);
1752   }
1753 #endif
1754   if(sbstart == -1) {
1755     // goto next sblock
1756     GC_BAMBOO_DEBUGPRINT(0xecc2);
1757     orig->sblockindex += 1;
1758     orig->blockbase += BAMBOO_SMEM_SIZE;
1759     goto outernextSBlock;
1760   } else if((sbstart != 0) && (sbchanged)) {
1761     // the first time to access this SBlock
1762     GC_BAMBOO_DEBUGPRINT(0xecc3);
1763     // not start from the very beginning
1764     orig->blockbase = sbstart;
1765   }  // if(gcsbstarttbl[orig->sblockindex] == -1) else ...
1766
1767   // setup information for this sblock
1768   orig->blockbound = orig->blockbase+(unsigned int)*((int*)(orig->blockbase));
1769   orig->offset = BAMBOO_CACHE_LINE_SIZE;
1770   orig->ptr = orig->blockbase + orig->offset;
1771   GC_BAMBOO_DEBUGPRINT(0xecc4);
1772   GC_BAMBOO_DEBUGPRINT_REG(orig->base);
1773   GC_BAMBOO_DEBUGPRINT_REG(orig->bound);
1774   GC_BAMBOO_DEBUGPRINT_REG(orig->ptr);
1775   GC_BAMBOO_DEBUGPRINT_REG(orig->blockbound);
1776   GC_BAMBOO_DEBUGPRINT_REG(orig->blockbase);
1777   GC_BAMBOO_DEBUGPRINT_REG(orig->offset);
1778   if(orig->ptr >= orig->bound) {
1779     // met a lobj, move to next block
1780     goto innernextSBlock;
1781   }
1782
1783   return true;
1784 } // bool nextSBlock(struct moveHelper * orig)
1785
1786 // return false if there are no available data to compact
1787 inline bool initOrig_Dst(struct moveHelper * orig,
1788                          struct moveHelper * to) {
1789   // init the dst ptr
1790   to->numblocks = 0;
1791   to->top = to->offset = BAMBOO_CACHE_LINE_SIZE;
1792   to->bound = BAMBOO_SMEM_SIZE_L;
1793   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1794
1795   GC_BAMBOO_DEBUGPRINT(0xef01);
1796   GC_BAMBOO_DEBUGPRINT_REG(to->base);
1797   unsigned int tobase = to->base;
1798   to->ptr = tobase + to->offset;
1799 #ifdef GC_CACHE_ADAPT
1800   // initialize the gc_cache_revise_information
1801   gc_cache_revise_infomation.to_page_start_va = to->ptr;
1802   unsigned int toindex = (unsigned int)(tobase-gcbaseva)/(BAMBOO_PAGE_SIZE);
1803   gc_cache_revise_infomation.to_page_end_va = (BAMBOO_PAGE_SIZE)*
1804         (toindex+1);
1805   gc_cache_revise_infomation.to_page_index = toindex;
1806   gc_cache_revise_infomation.orig_page_start_va = -1;
1807 #endif // GC_CACHE_ADAPT
1808
1809   // init the orig ptr
1810   orig->numblocks = 0;
1811   orig->base = tobase;
1812   unsigned int blocknum = 0;
1813   BLOCKINDEX(orig->base, &blocknum);
1814   unsigned int origbase = orig->base;
1815   // check the bamboo_smemtbl to decide the real bound
1816   orig->bound = origbase + (unsigned int)bamboo_smemtbl[blocknum];
1817 #ifdef GC_TBL_DEBUG
1818   if((orig->sblockindex) >= gcsbstarttbl_len) {
1819         BAMBOO_EXIT(0xb014);
1820   }
1821 #endif
1822   orig->blockbase = origbase;
1823   orig->sblockindex = (unsigned int)(origbase - gcbaseva) / BAMBOO_SMEM_SIZE;
1824   GC_BAMBOO_DEBUGPRINT(0xef02);
1825   GC_BAMBOO_DEBUGPRINT_REG(origbase);
1826   GC_BAMBOO_DEBUGPRINT_REG(orig->sblockindex);
1827   GC_BAMBOO_DEBUGPRINT_REG(gcsbstarttbl);
1828   GC_BAMBOO_DEBUGPRINT_REG(gcsbstarttbl[orig->sblockindex]);
1829
1830   int sbstart = gcsbstarttbl[orig->sblockindex];
1831 #ifdef GC_TBL_DEBUG
1832   if((orig->sblockindex) >= gcsbstarttbl_len) {
1833         BAMBOO_EXIT(0xb015);
1834   }
1835 #endif
1836   if(sbstart == -1) {
1837     GC_BAMBOO_DEBUGPRINT(0xef03);
1838     // goto next sblock
1839     orig->blockbound =
1840       gcbaseva+BAMBOO_SMEM_SIZE*(orig->sblockindex+1);
1841     return nextSBlock(orig);
1842   } else if(sbstart != 0) {
1843     GC_BAMBOO_DEBUGPRINT(0xef04);
1844     orig->blockbase = sbstart;
1845   }
1846   GC_BAMBOO_DEBUGPRINT(0xef05);
1847   orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
1848   orig->offset = BAMBOO_CACHE_LINE_SIZE;
1849   orig->ptr = orig->blockbase + orig->offset;
1850   GC_BAMBOO_DEBUGPRINT(0xef06);
1851   GC_BAMBOO_DEBUGPRINT_REG(orig->base);
1852
1853   return true;
1854 } // bool initOrig_Dst(struct moveHelper * orig, struct moveHelper * to)
1855
1856 inline void nextBlock(struct moveHelper * to) {
1857   to->top = to->bound + BAMBOO_CACHE_LINE_SIZE; // header!
1858   to->bound += BAMBOO_SMEM_SIZE;
1859   to->numblocks++;
1860   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
1861   to->offset = BAMBOO_CACHE_LINE_SIZE;
1862   to->ptr = to->base + to->offset;
1863 } // void nextBlock(struct moveHelper * to)
1864
1865 #ifdef GC_CACHE_ADAPT
1866 inline void samplingDataConvert(int current_ptr) {
1867   unsigned int tmp_factor = 
1868         current_ptr-gc_cache_revise_infomation.to_page_start_va;
1869   int topage=gc_cache_revise_infomation.to_page_index;
1870   int oldpage = gc_cache_revise_infomation.orig_page_index;
1871   unsigned int * newtable=&gccachesamplingtbl_r[topage];
1872   unsigned int * oldtable=&gccachesamplingtbl[oldpage];
1873   
1874   for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
1875     (*newtable) = ((*newtable)+(*oldtable)*tmp_factor);
1876     newtable=(unsigned int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
1877     oldtable=(unsigned int*) (((char *)oldtable)+size_cachesamplingtbl_local);
1878   }
1879 } // inline void samplingDataConvert(int)
1880
1881 inline void completePageConvert(struct moveHelper * orig,
1882                                     struct moveHelper * to,
1883                                                                 unsigned int current_ptr,
1884                                                                 bool closeToPage) {
1885   unsigned int ptr = 0;
1886   int tocompare = 0;
1887   if(closeToPage) {
1888         ptr = to->ptr;
1889         tocompare = gc_cache_revise_infomation.to_page_end_va;
1890   } else {
1891          ptr = orig->ptr;
1892          tocompare = gc_cache_revise_infomation.orig_page_end_va;
1893   }
1894   if(ptr >= tocompare) {
1895         // end of an orig/to page
1896         // compute the impact of this page for the new page
1897         samplingDataConvert(current_ptr);
1898         // prepare for an new orig page
1899         int tmp_index = (orig->ptr-gcbaseva)/(BAMBOO_PAGE_SIZE);
1900         gc_cache_revise_infomation.orig_page_start_va = orig->ptr;
1901         gc_cache_revise_infomation.orig_page_end_va = gcbaseva + 
1902           (BAMBOO_PAGE_SIZE)*(tmp_index+1);
1903         gc_cache_revise_infomation.orig_page_index = tmp_index;
1904         gc_cache_revise_infomation.to_page_start_va = to->ptr;
1905         if(closeToPage) {
1906           gc_cache_revise_infomation.to_page_end_va = gcbaseva + 
1907                 (BAMBOO_PAGE_SIZE)*((to->ptr-gcbaseva)/(BAMBOO_PAGE_SIZE)+1);
1908           gc_cache_revise_infomation.to_page_index = 
1909                 (to->ptr-gcbaseva)/(BAMBOO_PAGE_SIZE);
1910         }
1911   }
1912 } // inline void completePageConvert(...)
1913 #endif // GC_CACHE_ADAPT
1914
1915 // endaddr does not contain spaces for headers
1916 inline bool moveobj(struct moveHelper * orig,
1917                     struct moveHelper * to,
1918                     unsigned int stopblock) {
1919   if(stopblock == 0) {
1920     return true;
1921   }
1922
1923   GC_BAMBOO_DEBUGPRINT(0xe201);
1924   GC_BAMBOO_DEBUGPRINT_REG(orig->ptr);
1925   GC_BAMBOO_DEBUGPRINT_REG(to->ptr);
1926 #ifdef GC_TBL_DEBUG
1927   unsigned int bkptr = (unsigned int)(orig->ptr);
1928
1929   if((unsigned int)(to->ptr) > (unsigned int)(orig->ptr)) {
1930         tprintf("Error to->ptr > orig->ptr: %x, %x \n", (int)(to->ptr), (int)(orig->ptr));
1931         BAMBOO_EXIT(0xb016);
1932   }
1933 #endif
1934
1935   int type = 0;
1936   unsigned int size = 0;
1937   unsigned int isize = 0;
1938 innermoveobj:
1939   /*while((*((char*)(orig->ptr))) == (char)(-2)) {
1940         orig->ptr = (unsigned int)((void*)(orig->ptr) + 1);
1941   }*/
1942 #ifdef GC_CACHE_ADAPT
1943   completePageConvert(orig, to, to->ptr, false);
1944 #endif
1945   unsigned int origptr = (unsigned int)(orig->ptr);
1946   unsigned int origbound = (unsigned int)orig->bound;
1947   unsigned int origblockbound = (unsigned int)orig->blockbound;
1948   if((origptr >= origbound) || (origptr == origblockbound)) {
1949     if(!nextSBlock(orig)) {
1950       // finished, no more data
1951 #ifdef GC_TBL_DEBUG
1952           tprintf("AAAA %x \n", (int)(orig->ptr));
1953 #endif
1954       return true;
1955     }
1956     goto innermoveobj;
1957   }
1958   GC_BAMBOO_DEBUGPRINT(0xe202);
1959   GC_BAMBOO_DEBUGPRINT_REG(origptr);
1960   GC_BAMBOO_DEBUGPRINT(((int *)(origptr))[0]);
1961   // check the obj's type, size and mark flag
1962   type = ((int *)(origptr))[0];
1963   size = 0;
1964   if(type == 0) {
1965         // end of this block, go to next one
1966     if(!nextSBlock(orig)) {
1967       // finished, no more data
1968 #ifdef GC_TBL_DEBUG
1969           tprintf("BBBB %x \n", (int)(orig->ptr));
1970 #endif
1971       return true;
1972     }
1973     goto innermoveobj;
1974   } else if(type < NUMCLASSES) {
1975     // a normal object
1976     size = classsize[type];
1977   } else {
1978     // an array
1979     struct ArrayObject *ao=(struct ArrayObject *)(origptr);
1980     unsigned int elementsize=classsize[type];
1981     unsigned int length=ao->___length___;
1982     size=(unsigned int)sizeof(struct ArrayObject)
1983           +(unsigned int)(length*elementsize);
1984   }
1985   GC_BAMBOO_DEBUGPRINT(0xe203);
1986   GC_BAMBOO_DEBUGPRINT_REG(origptr);
1987   GC_BAMBOO_DEBUGPRINT_REG(size);
1988   ALIGNSIZE(size, &isize);       // no matter is the obj marked or not
1989                                  // should be able to across
1990 #ifdef GC_TBL_DEBUG
1991   int sindex = OBJMAPPINGINDEX((unsigned int)bkptr);
1992   int eindex = OBJMAPPINGINDEX((unsigned int)(origptr));
1993   for(int tmpi = sindex+1; tmpi < eindex; tmpi++) {
1994         if((gcmappingtbl[tmpi] != 0) && 
1995                 (hostcore(gcbaseva+bamboo_baseobjsize*tmpi)==BAMBOO_NUM_OF_CORE) && 
1996                 (hostcore(gcbaseva+bamboo_baseobjsize*(tmpi+1))==BAMBOO_NUM_OF_CORE)) {
1997           tprintf("Error moveobj --: %x, %x, %x, %d, %x \n", (int)bkptr, 
1998                   (int)origptr, (int)(gcbaseva+bamboo_baseobjsize*tmpi), 
1999                   (int)gcmappingtbl[tmpi], (int)(*((char*)(bkptr))));
2000           BAMBOO_EXIT(0xb017);
2001         }
2002   }
2003 #endif
2004   if(((int *)(origptr))[BAMBOOMARKBIT] == MARKED) {
2005         unsigned int totop = (unsigned int)to->top;
2006         unsigned int tobound = (unsigned int)to->bound;
2007     GC_BAMBOO_DEBUGPRINT(0xe204);
2008 #ifdef GC_PROFILE
2009 #ifdef MGC_SPEC
2010         if((STARTUPCORE != BAMBOO_NUM_OF_CORE) || gc_profile_flag) {
2011 #endif
2012         gc_num_liveobj++;
2013 #ifdef MGC_SPEC
2014         }
2015 #endif
2016 #endif
2017     // marked obj, copy it to current heap top
2018     // check to see if remaining space is enough
2019     if((unsigned int)(totop + isize) > tobound) {
2020       // fill 0 indicating the end of this block
2021       BAMBOO_MEMSET_WH(to->ptr,  '\0', tobound - totop);
2022       // fill the header of this block and then go to next block
2023       to->offset += tobound - totop;
2024       BAMBOO_MEMSET_WH(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
2025       (*((int*)(to->base))) = to->offset;
2026 #ifdef GC_CACHE_ADAPT
2027           unsigned int tmp_ptr = to->ptr;
2028 #endif // GC_CACHE_ADAPT
2029       nextBlock(to);
2030 #ifdef GC_CACHE_ADAPT
2031           completePageConvert(orig, to, tmp_ptr, true);
2032 #endif // GC_CACHE_ADAPT
2033       if(stopblock == to->numblocks) {
2034                 // already fulfilled the block
2035 #ifdef GC_TBL_DEBUG
2036                 tprintf("CCCC %x \n", (int)(orig->ptr));
2037 #endif
2038                 return true;
2039       }   // if(stopblock == to->numblocks)
2040     }   // if(to->top + isize > to->bound)
2041     // set the mark field to 2, indicating that this obj has been moved
2042     // and need to be flushed
2043     ((int *)(origptr))[BAMBOOMARKBIT] = COMPACTED;
2044         unsigned int toptr = (unsigned int)to->ptr;
2045 #ifdef GC_TBL_DEBUG
2046         {
2047           // scan all pointers in ptr
2048           unsigned int * tt_pointer;
2049           tt_pointer=pointerarray[type];
2050           if (tt_pointer==0) {
2051                 /* Array of primitives */
2052                 /* Do nothing */
2053           } else if (((unsigned int)tt_pointer)==1) {
2054                 /* Array of pointers */
2055                 struct ArrayObject *ao=(struct ArrayObject *)(origptr);
2056                 int tt_length=ao->___length___;
2057                 int tt_j;
2058                 for(tt_j=0; tt_j<tt_length; tt_j++) {
2059                   void *objptr =
2060                         ((void **)(((char *)&ao->___length___)+sizeof(int)))[tt_j];
2061                   if((objptr != 0) && 
2062                           ((gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 0) || 
2063                            (gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 1))) {
2064                         tprintf("Error moveobj, missing live obj ++: %x, %x, %d, %d, %d, %d, %d, %d, %d, %d \n", 
2065                                 (int)origptr, (int)objptr, __LINE__, tt_j, 
2066                                 ((int *)(origptr))[0], ((int *)(objptr))[0], 
2067                                 ((int *)(objptr))[BAMBOOMARKBIT], 
2068                                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)], 
2069                                 hostcore(objptr), BAMBOO_NUM_OF_CORE);
2070                         BAMBOO_EXIT(0xb018);
2071                   }
2072                 }
2073                 /* check the ArrayObject struct first*/
2074                 {
2075                   tt_pointer=pointerarray[OBJECTTYPE];
2076                   //handle object class
2077                   unsigned int size=tt_pointer[0];
2078                   int i;
2079                   for(i=1; i<=size; i++) {
2080                         unsigned int offset=tt_pointer[i];
2081                         void * objptr=*((void **)(((char *)ao)+offset));
2082                         if((objptr != 0) && 
2083                                 ((gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 0) ||
2084                                  (gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 1))) {
2085                           tprintf("Error moveobj, missing live obj ++: %x, %x, %d, %d, %d, %d, %d, %d, %d, %d \n", 
2086                                   (int)origptr, (int)objptr, __LINE__, tt_j, 
2087                                   ((int *)(origptr))[0], ((int *)(objptr))[0], 
2088                                   ((int *)(objptr))[BAMBOOMARKBIT], 
2089                                   gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)], 
2090                                   hostcore(objptr), BAMBOO_NUM_OF_CORE);
2091                           BAMBOO_EXIT(0xb019);
2092                         }
2093                   }
2094                 }
2095           } else {
2096                 unsigned int tt_size=tt_pointer[0];
2097                 int tt_i;
2098                 for(tt_i=1; tt_i<=tt_size; tt_i++) {
2099                   unsigned int tt_offset=tt_pointer[tt_i];
2100                   void * objptr=*((void **)(((char *)origptr)+tt_offset));
2101                   if((objptr!= 0) && 
2102                           ((gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 0) || 
2103                            (gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 1))) {
2104                         tprintf("Error moveobj, missing live obj ++: %x, %x, %d, %d, %d, %d, %d, %d, %d, %d \n", 
2105                                 (int)origptr, (int)objptr, __LINE__, tt_i,
2106                                 ((int *)(origptr))[0], ((int *)(objptr))[0],
2107                                 ((int *)(objptr))[BAMBOOMARKBIT], 
2108                                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)], 
2109                                 hostcore(objptr), BAMBOO_NUM_OF_CORE);
2110                         BAMBOO_EXIT(0xb01a);
2111                   }
2112                 }
2113           }     // if (pointer==0) else if ... else ...
2114         }
2115         if((unsigned int)(toptr) > (unsigned int)(origptr)) {
2116           tprintf("Error to->ptr > orig->ptr: %x, %x \n", (int)(toptr), 
2117                   (int)(origptr));
2118           BAMBOO_EXIT(0xb01b);
2119         }
2120 #endif
2121     if(toptr != origptr) {
2122       if((unsigned int)(origptr) < (unsigned int)(toptr+size)) {
2123                 memmove(toptr, origptr, size);
2124       } else {
2125                 memcpy(toptr, origptr, size);
2126       }
2127       // fill the remaining space with -2
2128       BAMBOO_MEMSET_WH((unsigned int)(toptr+size), -2, isize-size);
2129     }
2130 #ifdef GC_TBL_DEBUG
2131         if((gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)] != 2)) {
2132           tprintf("Error moveobj: %x, %x, %d \n", (int)origptr, 
2133                   ((int *)(origptr))[BAMBOOMARKBIT], 
2134                   gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)]);
2135           BAMBOO_EXIT(0xb01c);
2136         }
2137 #endif
2138     // store mapping info
2139         gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)]=(unsigned int)toptr;
2140 #ifdef GC_TBL_DEBUG
2141         if(gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)] == 
2142                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)-1]) {
2143           tprintf("Error moveobj ++ : %x, %x, %d \n", (int)origptr, (int)toptr, 
2144                   OBJMAPPINGINDEX((unsigned int)origptr));
2145           BAMBOO_EXIT(0xb01d);
2146         }
2147         // scan all pointers in ptr
2148         unsigned int * tt_pointer;
2149         tt_pointer=pointerarray[type];
2150         if (tt_pointer==0) {
2151           /* Array of primitives */
2152           /* Do nothing */
2153         } else if (((unsigned int)tt_pointer)==1) {
2154           /* Array of pointers */
2155           struct ArrayObject *ao=(struct ArrayObject *)(toptr);
2156           int tt_length=ao->___length___;
2157           int tt_j;
2158           for(tt_j=0; tt_j<tt_length; tt_j++) {
2159                 void *objptr =
2160                   ((void **)(((char *)&ao->___length___)+sizeof(int)))[tt_j];
2161                 
2162           }
2163           /* check the ArrayObject struct first*/
2164           {
2165                 tt_pointer=pointerarray[OBJECTTYPE];
2166                 //handle object class
2167                 unsigned int size=tt_pointer[0];
2168                 int i;
2169                 for(i=1; i<=size; i++) {
2170                   unsigned int offset=tt_pointer[i];
2171                   void * objptr=*((void **)(((char *)ao)+offset));
2172                   if((objptr != 0) && 
2173                           (gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 0)) {
2174                         tprintf("Error moveobj, missing live obj ++: %x, %x, %d, %d, %d, %d, %d, %d, %d, %d \n",
2175                                 (int)origptr, (int)objptr, __LINE__, tt_j, 
2176                                 ((int *)(origptr))[0], ((int *)(objptr))[0], 
2177                                 ((int *)(objptr))[BAMBOOMARKBIT], 
2178                                 gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)], 
2179                                 hostcore(objptr), BAMBOO_NUM_OF_CORE);
2180                           BAMBOO_EXIT(0xb01e);
2181                   }
2182                 }
2183           }
2184         } else {
2185           unsigned int tt_size=tt_pointer[0];
2186           int tt_i;
2187           for(tt_i=1; tt_i<=tt_size; tt_i++) {
2188                 unsigned int tt_offset=tt_pointer[tt_i];
2189                 void * objptr=*((void **)(((char *)toptr)+tt_offset));
2190                 if((objptr != 0) && 
2191                         (gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)] == 0)) {
2192                   tprintf("Error moveobj, missing live obj ++: %x, %x, %d, %d, %d, %d, %d, %d, %d, %d \n", 
2193                           (int)origptr, (int)objptr, __LINE__, tt_i, 
2194                           ((int *)(origptr))[0], ((int *)(objptr))[0], 
2195                           ((int *)(objptr))[BAMBOOMARKBIT], 
2196                           gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)], 
2197                           hostcore(objptr), BAMBOO_NUM_OF_CORE);
2198                   BAMBOO_EXIT(0xb01f);
2199                 }
2200           }
2201         }     // if (pointer==0) else if ... else ...
2202         if(!ISSHAREDOBJ(toptr)) {
2203           tprintf("Error: %x, %x \n", (int)origptr, (int)toptr);
2204           BAMBOO_EXIT(0xb020);
2205         }
2206 #endif
2207         GC_BAMBOO_DEBUGPRINT(0xcdce);
2208     GC_BAMBOO_DEBUGPRINT_REG(origptr);
2209     GC_BAMBOO_DEBUGPRINT_REG(toptr);
2210     GC_BAMBOO_DEBUGPRINT_REG(isize);
2211     gccurr_heaptop -= isize;
2212     to->ptr += isize;
2213     to->offset += isize;
2214     to->top += isize;
2215 #ifdef GC_CACHE_ADAPT
2216         unsigned int tmp_ptr = to->ptr;
2217 #endif // GC_CACHE_ADAPT
2218     if(to->top == to->bound) {
2219       // fill the header of this block and then go to next block
2220       BAMBOO_MEMSET_WH(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
2221       (*((int*)(to->base))) = to->offset;
2222       nextBlock(to);
2223     }
2224 #ifdef GC_CACHE_ADAPT
2225         completePageConvert(orig, to, tmp_ptr, true);
2226 #endif // GC_CACHE_ADAPT
2227   } // if(mark == 1)
2228 #ifdef GC_TBL_DEBUG
2229   else {
2230         // skip the whole obj
2231         int sindex = OBJMAPPINGINDEX((unsigned int)origptr);
2232         int eindex = OBJMAPPINGINDEX((unsigned int)(origptr+size));
2233         for(int tmpi = sindex; tmpi < eindex; tmpi++) {
2234           if((gcmappingtbl[tmpi] != 0) && 
2235                   (hostcore(gcbaseva+bamboo_baseobjsize*tmpi)==BAMBOO_NUM_OF_CORE) && 
2236                   (hostcore(gcbaseva+bamboo_baseobjsize*(tmpi+1))==BAMBOO_NUM_OF_CORE))
2237           {
2238                 tprintf("Error moveobj **: %x, %x, %x, %d, (%d, %d, %x) \n", 
2239                         (int)origptr, (int)(origptr+isize), 
2240                         (int)(gcbaseva+bamboo_baseobjsize*tmpi), gcmappingtbl[tmpi], type,
2241                         isize, ((int *)(origptr))[BAMBOOMARKBIT]);
2242                 BAMBOO_EXIT(0xb021);
2243           }
2244         }
2245   }
2246 #endif
2247   GC_BAMBOO_DEBUGPRINT(0xe205);
2248   
2249   // move to next obj
2250   orig->ptr += isize; // size;
2251
2252 #ifdef GC_TBL_DEBUG
2253   if(!ISSHAREDOBJ(orig->ptr) || !ISSHAREDOBJ(to->ptr)) {
2254         tprintf("Error moveobj out of boundary: %x, %x, %d, %d \n", 
2255                 (int)(orig->ptr), (int)(to->ptr), size, isize);
2256         BAMBOO_EXIT(0x2022);
2257   }
2258 #endif
2259
2260   GC_BAMBOO_DEBUGPRINT_REG(isize);
2261   GC_BAMBOO_DEBUGPRINT_REG(size);
2262   GC_BAMBOO_DEBUGPRINT_REG(orig->ptr);
2263   GC_BAMBOO_DEBUGPRINT_REG(orig->bound);
2264   if(((unsigned int)(orig->ptr) > (unsigned int)(orig->bound))
2265           || ((unsigned int)(orig->ptr) == (unsigned int)(orig->blockbound))) {
2266     GC_BAMBOO_DEBUGPRINT(0xe206);
2267     if(!nextSBlock(orig)) {
2268       // finished, no more data
2269 #ifdef GC_TBL_DEBUG
2270           tprintf("DDDD %x \n", (int)(orig->ptr));
2271 #endif
2272       return true;
2273     }
2274   }
2275   GC_BAMBOO_DEBUGPRINT(0xe207);
2276   GC_BAMBOO_DEBUGPRINT_REG(orig->ptr);
2277   return false;
2278 } //bool moveobj(struct moveHelper* orig,struct moveHelper* to,int* endaddr)
2279
2280 // should be invoked with interrupt closed
2281 inline int assignSpareMem_I(unsigned int sourcecore,
2282                             unsigned int * requiredmem,
2283                             unsigned int * tomove,
2284                             unsigned int * startaddr) {
2285   unsigned int b = 0;
2286   BLOCKINDEX(gcloads[sourcecore], &b);
2287   unsigned int boundptr = (b<NUMCORES4GC) ? ((b+1)*BAMBOO_SMEM_SIZE_L)
2288                  : (BAMBOO_LARGE_SMEM_BOUND+(b-NUMCORES4GC+1)*BAMBOO_SMEM_SIZE);
2289   unsigned int remain = boundptr - gcloads[sourcecore];
2290   unsigned int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
2291   *startaddr = gcloads[sourcecore];
2292   *tomove = gcfilledblocks[sourcecore] + 1;
2293   if(memneed < remain) {
2294     gcloads[sourcecore] += memneed;
2295     return 0;
2296   } else {
2297     // next available block
2298     gcfilledblocks[sourcecore] += 1;
2299     unsigned int newbase = 0;
2300     BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
2301     gcloads[sourcecore] = newbase;
2302     return requiredmem-remain;
2303   }
2304 } // int assignSpareMem_I(int ,int * , int * , int * )
2305
2306 // should be invoked with interrupt closed
2307 inline bool gcfindSpareMem_I(unsigned int * startaddr,
2308                              unsigned int * tomove,
2309                              unsigned int * dstcore,
2310                              unsigned int requiredmem,
2311                              unsigned int requiredcore) {
2312   for(int k = 0; k < NUMCORES4GC; k++) {
2313     if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
2314       // check if this stopped core has enough mem
2315       assignSpareMem_I(k, requiredmem, tomove, startaddr);
2316       *dstcore = k;
2317       return true;
2318     }
2319   }
2320   // if can not find spare mem right now, hold the request
2321   gcrequiredmems[requiredcore] = requiredmem;
2322   gcmovepending++;
2323   return false;
2324 } //bool gcfindSpareMem_I(int* startaddr,int* tomove,int mem,int core)
2325
2326 inline bool compacthelper(struct moveHelper * orig,
2327                           struct moveHelper * to,
2328                           int * filledblocks,
2329                           unsigned int * heaptopptr,
2330                           bool * localcompact) {
2331   // scan over all objs in this block, compact the marked objs
2332   // loop stop when finishing either scanning all active objs or
2333   // fulfilled the gcstopblock
2334   GC_BAMBOO_DEBUGPRINT(0xe101);
2335   GC_BAMBOO_DEBUGPRINT_REG(gcblock2fill);
2336   GC_BAMBOO_DEBUGPRINT_REG(gcmarkedptrbound);
2337 innercompact:
2338   while((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
2339     bool stop = moveobj(orig, to, gcblock2fill);
2340     if(stop) {
2341       break;
2342     }
2343   }
2344 #ifdef GC_TBL_DEBUG
2345   tprintf("finish mark %x \n", (int)gcmarkedptrbound);
2346 #endif
2347 #ifdef GC_CACHE_ADAPT
2348   // end of an to page, wrap up its information
2349   samplingDataConvert(to->ptr);
2350 #endif // GC_CACHE_ADAPT
2351   // if no objs have been compact, do nothing,
2352   // otherwise, fill the header of this block
2353   if(to->offset > (unsigned int)BAMBOO_CACHE_LINE_SIZE) {
2354     BAMBOO_MEMSET_WH(to->base, '\0', BAMBOO_CACHE_LINE_SIZE);
2355     (*((int*)(to->base))) = to->offset;
2356   } else {
2357     to->offset = 0;
2358     to->ptr = to->base;
2359     to->top -= BAMBOO_CACHE_LINE_SIZE;
2360   }  // if(to->offset > BAMBOO_CACHE_LINE_SIZE) else ...
2361   if(*localcompact) {
2362     *heaptopptr = to->ptr;
2363     *filledblocks = to->numblocks;
2364   }
2365   GC_BAMBOO_DEBUGPRINT(0xe102);
2366   GC_BAMBOO_DEBUGPRINT_REG(orig->ptr);
2367   GC_BAMBOO_DEBUGPRINT_REG(gcmarkedptrbound);
2368   GC_BAMBOO_DEBUGPRINT_REG(*heaptopptr);
2369   GC_BAMBOO_DEBUGPRINT_REG(*filledblocks);
2370   GC_BAMBOO_DEBUGPRINT_REG(gccurr_heaptop);
2371
2372   // send msgs to core coordinator indicating that the compact is finishing
2373   // send compact finish message to core coordinator
2374   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
2375     gcfilledblocks[BAMBOO_NUM_OF_CORE] = *filledblocks;
2376     gcloads[BAMBOO_NUM_OF_CORE] = *heaptopptr;
2377     if((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
2378       GC_BAMBOO_DEBUGPRINT(0xe103);
2379       // ask for more mem
2380       gctomove = false;
2381       BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2382       if(gcfindSpareMem_I(&gcmovestartaddr, &gcblock2fill, &gcdstcore,
2383                           gccurr_heaptop, BAMBOO_NUM_OF_CORE)) {
2384                 GC_BAMBOO_DEBUGPRINT(0xe104);
2385                 gctomove = true;
2386       } else {
2387                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2388                 GC_BAMBOO_DEBUGPRINT(0xe105);
2389                 return false;
2390       }
2391       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2392     } else {
2393       GC_BAMBOO_DEBUGPRINT(0xe106);
2394       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
2395       gctomove = false;
2396       return true;
2397     }
2398   } else {
2399     if((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
2400       GC_BAMBOO_DEBUGPRINT(0xe107);
2401       // ask for more mem
2402       gctomove = false;
2403       send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
2404                  *filledblocks, *heaptopptr, gccurr_heaptop, false);
2405     } else {
2406       GC_BAMBOO_DEBUGPRINT(0xe108);
2407       GC_BAMBOO_DEBUGPRINT_REG(*heaptopptr);
2408       // finish compacting
2409       send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
2410                  *filledblocks, *heaptopptr, 0, false);
2411     }
2412   }       // if(STARTUPCORE == BAMBOO_NUM_OF_CORE)
2413
2414   if(orig->ptr < gcmarkedptrbound) {
2415     GC_BAMBOO_DEBUGPRINT(0xe109);
2416     // still have unpacked obj
2417     while(true) {
2418       if(gctomove) {
2419                 break;
2420       }
2421     }
2422     ;
2423         gctomove = false;
2424     GC_BAMBOO_DEBUGPRINT(0xe10a);
2425
2426     to->ptr = gcmovestartaddr;
2427     to->numblocks = gcblock2fill - 1;
2428     to->bound = (to->numblocks==0) ?
2429                 BAMBOO_SMEM_SIZE_L :
2430                 BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
2431     BASEPTR(gcdstcore, to->numblocks, &(to->base));
2432     to->offset = to->ptr - to->base;
2433     to->top = (to->numblocks==0) ?
2434               (to->offset) : (to->bound-BAMBOO_SMEM_SIZE+to->offset);
2435     to->base = to->ptr;
2436     to->offset = BAMBOO_CACHE_LINE_SIZE;
2437     to->ptr += to->offset;   // for header
2438     to->top += to->offset;
2439     if(gcdstcore == BAMBOO_NUM_OF_CORE) {
2440       *localcompact = true;
2441     } else {
2442       *localcompact = false;
2443     }
2444 #ifdef GC_CACHE_ADAPT
2445         // initialize the gc_cache_revise_information
2446         gc_cache_revise_infomation.to_page_start_va = to->ptr;
2447         gc_cache_revise_infomation.to_page_end_va = gcbaseva + 
2448           (BAMBOO_PAGE_SIZE)*((to->base-gcbaseva)/(BAMBOO_PAGE_SIZE)+1);
2449         gc_cache_revise_infomation.to_page_index = 
2450           (to->base-gcbaseva)/(BAMBOO_PAGE_SIZE);
2451         gc_cache_revise_infomation.orig_page_start_va = orig->ptr;
2452         gc_cache_revise_infomation.orig_page_end_va = gcbaseva + 
2453           (BAMBOO_PAGE_SIZE)*((orig->ptr-gcbaseva)/(BAMBOO_PAGE_SIZE)+1);
2454         gc_cache_revise_infomation.orig_page_index = 
2455           (orig->blockbase-gcbaseva)/(BAMBOO_PAGE_SIZE);
2456 #endif // GC_CACHE_ADAPT
2457     goto innercompact;
2458   }
2459   GC_BAMBOO_DEBUGPRINT(0xe10b);
2460   return true;
2461 } // void compacthelper()
2462
2463 inline void compact() {
2464   if(COMPACTPHASE != gcphase) {
2465     BAMBOO_EXIT(0xb023);
2466   }
2467
2468   // initialize pointers for comapcting
2469   struct moveHelper * orig =
2470     (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
2471   struct moveHelper * to =
2472     (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
2473   if(!initOrig_Dst(orig, to)) {
2474     // no available data to compact
2475     // send compact finish msg to STARTUP core
2476     GC_BAMBOO_DEBUGPRINT(0xe001);
2477     GC_BAMBOO_DEBUGPRINT_REG(to->base);
2478     send_msg_5(STARTUPCORE, GCFINISHCOMPACT, BAMBOO_NUM_OF_CORE,
2479                0, to->base, 0, false);
2480     RUNFREE(orig);
2481     RUNFREE(to);
2482     return;
2483   }
2484 #ifdef GC_CACHE_ADAPT
2485   gc_cache_revise_infomation.orig_page_start_va = orig->ptr;
2486   gc_cache_revise_infomation.orig_page_end_va = gcbaseva +  
2487         (BAMBOO_PAGE_SIZE)*((orig->ptr-gcbaseva)/(BAMBOO_PAGE_SIZE)+1);
2488   gc_cache_revise_infomation.orig_page_index = 
2489         (orig->blockbase-gcbaseva)/(BAMBOO_PAGE_SIZE);
2490 #endif // GC_CACHE_ADAPT
2491
2492   unsigned int filledblocks = 0;
2493   unsigned int heaptopptr = 0;
2494   bool localcompact = true;
2495   compacthelper(orig, to, &filledblocks, &heaptopptr, &localcompact);
2496   RUNFREE(orig);
2497   RUNFREE(to);
2498 } // compact()
2499
2500 // if return NULL, means
2501 //   1. objptr is NULL
2502 //   2. objptr is not a shared obj
2503 // in these cases, remain the original value is OK
2504 #ifdef GC_TBL_DEBUG
2505 inline void * flushObj(void * objptr, int linenum, void * ptr, int tt) {
2506 #else
2507 inline void * flushObj(void * objptr) {
2508 #endif
2509   GC_BAMBOO_DEBUGPRINT(0xe401);
2510   if(objptr == NULL) {
2511     return NULL;
2512   }
2513   void * dstptr = NULL;
2514   if(ISSHAREDOBJ(objptr)) {
2515     GC_BAMBOO_DEBUGPRINT(0xe402);
2516     GC_BAMBOO_DEBUGPRINT_REG(objptr);
2517     // a shared obj ptr, change to new address
2518         dstptr = gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)];
2519     GC_BAMBOO_DEBUGPRINT_REG(dstptr);
2520 #ifdef GC_TBL_DEBUG
2521         if(ISSHAREDOBJ(dstptr) && ((unsigned int)(((int*)dstptr)[0]) >= (unsigned int)NUMTYPES)) {
2522           tprintf("Error flushObj  ** : %x, %x, %d, %d, %d, %d, %x, %x, %x, %d, %x, %d %d \n", 
2523                   (int)objptr, (int)dstptr, ((int*)dstptr)[0], hostcore(objptr), 
2524                   hostcore(objptr)==BAMBOO_NUM_OF_CORE, 
2525                   OBJMAPPINGINDEX((unsigned int)objptr), (int)gcmappingtbl, 
2526                   &(gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)]), 
2527                   (int)gcbaseva, linenum, (int)ptr, ((int*)ptr)[0], tt);
2528           BAMBOO_EXIT(0xb024);
2529         }
2530 #endif
2531
2532     if(!ISSHAREDOBJ(dstptr)) {
2533 #ifdef GC_TBL_DEBUG
2534           tprintf("Error flushObj  ++ : %x, %x, %d, %d, %d, %x, %x, %x, %d, %x, %d %d \n", 
2535                   (int)objptr, (int)dstptr, hostcore(objptr), 
2536                   hostcore(objptr)==BAMBOO_NUM_OF_CORE, 
2537                   OBJMAPPINGINDEX((unsigned int)objptr), (int)gcmappingtbl, 
2538                   &(gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)]), 
2539                   (int)gcbaseva, linenum, (int)ptr, ((int*)ptr)[0], tt);
2540           tprintf("gcmappingtbl: \n");
2541           int tmp = OBJMAPPINGINDEX((unsigned int)objptr) - 50;
2542           for(int jj = 0; jj < 100; jj+=10) {
2543                 tprintf("%8x, %8x, %8x, %8x, %8x, %8x, %8x, %8x, %8x, %8x, %d \n", 
2544                         (int)gcmappingtbl[tmp++], (int)gcmappingtbl[tmp++], 
2545                         (int)gcmappingtbl[tmp++], (int)gcmappingtbl[tmp++], 
2546                         (int)gcmappingtbl[tmp++], (int)gcmappingtbl[tmp++], 
2547                         (int)gcmappingtbl[tmp++], (int)gcmappingtbl[tmp++], 
2548                         (int)gcmappingtbl[tmp++], (int)gcmappingtbl[tmp++], tmp);
2549           }
2550           BAMBOO_EXIT(0xb025);
2551 #else
2552       // no mapping info
2553       GC_BAMBOO_DEBUGPRINT(0xe403);
2554       GC_BAMBOO_DEBUGPRINT_REG(objptr);
2555       GC_BAMBOO_DEBUGPRINT_REG(hostcore(objptr));
2556           // error! the obj is right on this core, but cannot find it
2557           GC_BAMBOO_DEBUGPRINT_REG(objptr);
2558           tprintf("Error flushObj  ++ : %x, %x, %d, %d, %x, %x, %x, %x\n", 
2559                   (int)objptr, (int)dstptr, hostcore(objptr), 
2560                   hostcore(objptr)==BAMBOO_NUM_OF_CORE, 
2561                   OBJMAPPINGINDEX((unsigned int)objptr), (int)gcmappingtbl, 
2562                   &(gcmappingtbl[OBJMAPPINGINDEX((unsigned int)objptr)]), 
2563                   (int)gcbaseva);
2564           BAMBOO_EXIT(0xb026);
2565 #endif
2566     }  // if(NULL == dstptr)
2567   }   // if(ISSHAREDOBJ(objptr))
2568 #ifdef GC_TBL_DEBUG
2569   else {
2570         tprintf("Error flushObj: %x \n", (int)objptr);
2571         BAMBOO_EXIT(0xb027);
2572   }
2573 #endif
2574   // if not a shared obj, return NULL to indicate no need to flush
2575   GC_BAMBOO_DEBUGPRINT(0xe404);
2576   return dstptr;
2577 } // void flushObj(void * objptr)
2578
2579 inline void flushRuntimeObj(struct garbagelist * stackptr) {
2580   int i,j;
2581   // flush current stack
2582   while(stackptr!=NULL) {
2583     for(i=0; i<stackptr->size; i++) {
2584       if(stackptr->array[i] != NULL) {
2585 #ifdef GC_TBL_DEBUG
2586                 void * dst = flushObj(stackptr->array[i], 
2587                         __LINE__, stackptr->array[i], i);
2588 #else
2589                 void * dst = flushObj(stackptr->array[i]);
2590 #endif
2591                 if(dst != NULL) {
2592                   stackptr->array[i] = dst;
2593                 }
2594       }
2595     }
2596     stackptr=stackptr->next;
2597   }
2598
2599   // flush static pointers global_defs_p
2600   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
2601         struct garbagelist * staticptr=(struct garbagelist *)global_defs_p;
2602         for(i=0; i<staticptr->size; i++) {
2603           if(staticptr->array[i] != NULL) {
2604 #ifdef GC_TBL_DEBUG
2605                 void * dst = flushObj(staticptr->array[i], 
2606                         __LINE__, staticptr->array[i], i);
2607 #else
2608                 void * dst = flushObj(staticptr->array[i]);
2609 #endif
2610                 if(dst != NULL) {
2611                   staticptr->array[i] = dst;
2612                 }
2613           }
2614         }
2615   }
2616
2617 #ifdef TASK
2618   // flush objectsets
2619   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
2620     for(i=0; i<NUMCLASSES; i++) {
2621       struct parameterwrapper ** queues =
2622         objectqueues[BAMBOO_NUM_OF_CORE][i];
2623       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
2624       for(j = 0; j < length; ++j) {
2625                 struct parameterwrapper * parameter = queues[j];
2626                 struct ObjectHash * set=parameter->objectset;
2627                 struct ObjectNode * ptr=set->listhead;
2628                 while(ptr!=NULL) {
2629 #ifdef GC_TBL_DEBUG
2630                   void * dst = flushObj((void *)ptr->key, 
2631                           __LINE__, (void *)ptr->key, 0);
2632 #else
2633                   void * dst = flushObj((void *)ptr->key);
2634 #endif
2635                   if(dst != NULL) {
2636                         ptr->key = dst;
2637                   }
2638                   ptr=ptr->lnext;
2639                 }
2640                 ObjectHashrehash(set);
2641       }
2642     }
2643   }
2644
2645   // flush current task descriptor
2646   if(currtpd != NULL) {
2647     for(i=0; i<currtpd->numParameters; i++) {
2648 #ifdef GC_TBL_DEBUG
2649           void * dst = flushObj(currtpd->parameterArray[i], 
2650                   __LINE__, currtpd->parameterArray[i], i);
2651 #else
2652       void * dst = flushObj(currtpd->parameterArray[i]);
2653 #endif
2654       if(dst != NULL) {
2655                 currtpd->parameterArray[i] = dst;
2656       }
2657     }
2658   }
2659
2660   // flush active tasks
2661   if(activetasks != NULL) {
2662     struct genpointerlist * ptr=activetasks->list;
2663     while(ptr!=NULL) {
2664       struct taskparamdescriptor *tpd=ptr->src;
2665       int i;
2666       for(i=0; i<tpd->numParameters; i++) {
2667 #ifdef GC_TBL_DEBUG
2668                 void * dst = flushObj(tpd->parameterArray[i], 
2669                         __LINE__, tpd->parameterArray[i], i);
2670 #else
2671                 void * dst = flushObj(tpd->parameterArray[i]);
2672 #endif
2673                 if(dst != NULL) {
2674                   tpd->parameterArray[i] = dst;
2675                 }
2676       }
2677       ptr=ptr->inext;
2678     }
2679     genrehash(activetasks);
2680   }
2681
2682   // flush cached transferred obj
2683   struct QueueItem * tmpobjptr =  getHead(&objqueue);
2684   while(tmpobjptr != NULL) {
2685     struct transObjInfo * objInfo =
2686       (struct transObjInfo *)(tmpobjptr->objectptr);
2687 #ifdef GC_TBL_DEBUG
2688         void * dst = flushObj(objInfo->objptr, __LINE__, 
2689                 objInfo->objptr, 0);
2690 #else
2691     void * dst = flushObj(objInfo->objptr);
2692 #endif
2693     if(dst != NULL) {
2694       objInfo->objptr = dst;
2695     }
2696     tmpobjptr = getNextQueueItem(tmpobjptr);
2697   }
2698
2699   // flush cached objs to be transferred
2700   struct QueueItem * item = getHead(totransobjqueue);
2701   while(item != NULL) {
2702     struct transObjInfo * totransobj =
2703       (struct transObjInfo *)(item->objectptr);
2704 #ifdef GC_TBL_DEBUG
2705         void * dst = flushObj(totransobj->objptr, __LINE__, 
2706                 totransobj->objptr, 0);
2707 #else
2708     void * dst = flushObj(totransobj->objptr);
2709 #endif
2710     if(dst != NULL) {
2711       totransobj->objptr = dst;
2712     }
2713     item = getNextQueueItem(item);
2714   }  // while(item != NULL)
2715
2716   // enqueue lock related info
2717   for(i = 0; i < runtime_locklen; ++i) {
2718 #ifdef GC_TBL_DEBUG
2719         void * dst = flushObj(runtime_locks[i].redirectlock, 
2720                 __LINE__, runtime_locks[i], i);
2721 #else
2722     void * dst = flushObj(runtime_locks[i].redirectlock);
2723 #endif
2724     if(dst != NULL) {
2725       runtime_locks[i].redirectlock = (int)dst;
2726     }
2727     if(runtime_locks[i].value != NULL) {
2728 #ifdef GC_TBL_DEBUG
2729           void * dst=flushObj(runtime_locks[i].value, 
2730                   __LINE__, runtime_locks[i].value, i);
2731 #else
2732       void * dst=flushObj(runtime_locks[i].value);
2733 #endif
2734       if(dst != NULL) {
2735                 runtime_locks[i].value = (int)dst;
2736       }
2737     }
2738   }
2739 #endif
2740
2741 #ifdef MGC
2742   // flush the bamboo_threadlocks
2743   if(bamboo_threadlocks != 0) {
2744 #ifdef GC_TBL_DEBUG
2745         bamboo_threadlocks = 
2746           (unsigned int)(flushObj((void *)bamboo_threadlocks,
2747                         __LINE__, (void *)bamboo_threadlocks, 0));
2748 #else
2749         bamboo_threadlocks = (unsigned int)(flushObj((void *)bamboo_threadlocks));
2750 #endif
2751   }
2752
2753   // flush the bamboo_current_thread
2754   if(bamboo_current_thread != 0) {
2755 #ifdef GC_TBL_DEBUG
2756         bamboo_current_thread = 
2757           (unsigned int)(flushObj((void *)bamboo_current_thread,
2758                         __LINE__, (void *)bamboo_current_thread, 0));
2759 #else
2760         bamboo_current_thread = 
2761           (unsigned int)(flushObj((void *)bamboo_current_thread));
2762 #endif
2763   }
2764
2765   // flush global thread queue
2766   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
2767         unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
2768         if(thread_counter > 0) {
2769           unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
2770           for(i = thread_counter; i > 0; i--) {
2771 #ifdef GC_TBL_DEBUG
2772                 bamboo_thread_queue[4+start] = 
2773                   (INTPTR)(flushObj((void *)bamboo_thread_queue[4+start
2774                                 ], __LINE__, (void *)bamboo_thread_queue, 0));
2775 #else
2776                 bamboo_thread_queue[4+start] = 
2777                   (INTPTR)(flushObj((void *)bamboo_thread_queue[4+start]));
2778 #endif
2779                 start = (start+1)&bamboo_max_thread_num_mask;
2780           }
2781         }
2782         unlockthreadqueue();
2783   }
2784 #endif
2785 } // void flushRuntimeObj(struct garbagelist * stackptr)
2786
2787 inline void flush(struct garbagelist * stackptr) {
2788
2789   flushRuntimeObj(stackptr);
2790
2791   while(true) {
2792     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2793     bool hasItems = gc_moreItems_I();
2794     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2795     if(!hasItems) {
2796       break;
2797     }
2798
2799     GC_BAMBOO_DEBUGPRINT(0xe301);
2800     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
2801     void * ptr = gc_dequeue_I();
2802 #ifdef GC_TBL_DEBUG
2803     unsigned int bkptr = (unsigned int)ptr;
2804 #endif
2805     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
2806     if(ISSHAREDOBJ(ptr)) {
2807       // should be a local shared obj and should have mapping info
2808 #ifdef GC_TBL_DEBUG
2809           ptr = flushObj(ptr, __LINE__, ptr, 0);
2810 #else
2811       ptr = flushObj(ptr);
2812 #endif
2813       GC_BAMBOO_DEBUGPRINT(0xe302);
2814       GC_BAMBOO_DEBUGPRINT_REG(ptr);
2815       if(ptr == NULL) {
2816                 BAMBOO_EXIT(0xb028);
2817       }
2818     } // if(ISSHAREDOBJ(ptr))
2819     if((!ISSHAREDOBJ(ptr))||(((int *)(ptr))[BAMBOOMARKBIT] == COMPACTED)) {
2820       int type = ((int *)(ptr))[0];
2821 #ifdef GC_TBL_DEBUG
2822           if((unsigned int)type >= (unsigned int)NUMTYPES) {
2823                 tprintf("Error flushObj  %x, %x, %d, %d \n", bkptr, (int)ptr, type, 
2824                         ((int *)(ptr))[BAMBOOMARKBIT]);
2825                 BAMBOO_EXIT(0xb029);
2826           }
2827 #endif
2828       // scan all pointers in ptr
2829       unsigned int * pointer;
2830       pointer=pointerarray[type];
2831       GC_BAMBOO_DEBUGPRINT(0xe303);
2832       GC_BAMBOO_DEBUGPRINT_REG(pointer);
2833       if (pointer==0) {
2834                 /* Array of primitives */
2835                 /* Do nothing */
2836       } else if (((unsigned int)pointer)==1) {
2837                 GC_BAMBOO_DEBUGPRINT(0xe304);
2838                 /* Array of pointers */
2839                 struct ArrayObject *ao=(struct ArrayObject *) ptr;
2840                 int length=ao->___length___;
2841                 int j;
2842                 for(j=0; j<length; j++) {
2843                   GC_BAMBOO_DEBUGPRINT(0xe305);
2844                   void *objptr=
2845                         ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
2846                   GC_BAMBOO_DEBUGPRINT_REG(objptr);
2847                   if(objptr != NULL) {
2848 #ifdef GC_TBL_DEBUG
2849                         void * dst = flushObj(objptr, __LINE__, ptr, j);
2850 #else
2851                         void * dst = flushObj(objptr);
2852 #endif
2853                         if(dst != NULL) {
2854                           ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] = dst;
2855                         }
2856                   }
2857                 }
2858                 /* check the ArrayObject struct first*/
2859                 {
2860                   pointer=pointerarray[OBJECTTYPE];
2861                   //handle object class
2862                   unsigned int size=pointer[0];
2863                   int i;
2864                   for(i=1; i<=size; i++) {
2865                         unsigned int offset=pointer[i];
2866                         void * objptr=*((void **)(((char *)ao)+offset));
2867                         GC_BAMBOO_DEBUGPRINT_REG(objptr);
2868                         if(objptr != NULL) {
2869 #ifdef GC_TBL_DEBUG
2870                           void * dst = flushObj(objptr, __LINE__, ptr, j);
2871 #else
2872                           void * dst = flushObj(objptr);
2873 #endif
2874                           if(dst != NULL) {
2875                                 *((void **)(((char *)ao)+offset)) = dst;
2876                           }
2877                         }
2878                   }
2879                 }
2880       } else {
2881                 GC_BAMBOO_DEBUGPRINT(0xe306);
2882                 unsigned int size=pointer[0];
2883                 int i;
2884                 for(i=1; i<=size; i++) {
2885                   GC_BAMBOO_DEBUGPRINT(0xe307);
2886                   unsigned int offset=pointer[i];
2887                   void * objptr=*((void **)(((char *)ptr)+offset));
2888                   GC_BAMBOO_DEBUGPRINT_REG(objptr);
2889                   if(objptr != NULL) {
2890 #ifdef GC_TBL_DEBUG
2891                         void * dst = flushObj(objptr, __LINE__, ptr, i);
2892 #else
2893                         void * dst = flushObj(objptr);
2894 #endif
2895                         if(dst != NULL) {
2896                           *((void **)(((char *)ptr)+offset)) = dst;
2897                         }
2898                   }
2899                 } // for(i=1; i<=size; i++)
2900       }  // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
2901       // restore the mark field, indicating that this obj has been flushed
2902       if(ISSHAREDOBJ(ptr)) {
2903                 ((int *)(ptr))[BAMBOOMARKBIT] = INIT;
2904       }
2905     }  //if((!ISSHAREDOBJ(ptr))||(((int *)(ptr))[BAMBOOMARKBIT] == COMPACTED))
2906   }   // while(gc_moreItems())
2907   GC_BAMBOO_DEBUGPRINT(0xe308);
2908
2909   // TODO bug here: the startup core contains all lobjs' info, thus all the
2910   // lobjs are flushed in sequence.
2911   // flush lobjs
2912   while(gc_lobjmoreItems_I()) {
2913     GC_BAMBOO_DEBUGPRINT(0xe309);
2914     void * ptr = gc_lobjdequeue_I(NULL, NULL);
2915 #ifdef GC_TBL_DEBUG
2916         ptr = flushObj(ptr, __LINE__, ptr, 0);
2917 #else
2918     ptr = flushObj(ptr);
2919 #endif
2920     GC_BAMBOO_DEBUGPRINT(0xe30a);
2921     GC_BAMBOO_DEBUGPRINT_REG(ptr);
2922     GC_BAMBOO_DEBUGPRINT_REG(tptr);
2923     GC_BAMBOO_DEBUGPRINT_REG(((int *)(tptr))[0]);
2924     if(ptr == NULL) {
2925       BAMBOO_EXIT(0xb02a);
2926     }
2927     if(((int *)(ptr))[BAMBOOMARKBIT] == COMPACTED) {
2928       int type = ((int *)(ptr))[0];
2929       // scan all pointers in ptr
2930       unsigned int * pointer;
2931       pointer=pointerarray[type];
2932       GC_BAMBOO_DEBUGPRINT(0xe30b);
2933       GC_BAMBOO_DEBUGPRINT_REG(pointer);
2934       if (pointer==0) {
2935                 /* Array of primitives */
2936                 /* Do nothing */
2937       } else if (((unsigned int)pointer)==1) {
2938                 GC_BAMBOO_DEBUGPRINT(0xe30c);
2939                 /* Array of pointers */
2940                 struct ArrayObject *ao=(struct ArrayObject *) ptr;
2941                 int length=ao->___length___;
2942                 int j;
2943                 for(j=0; j<length; j++) {
2944                   GC_BAMBOO_DEBUGPRINT(0xe30d);
2945                   void *objptr=
2946                         ((void **)(((char *)&ao->___length___)+sizeof(int)))[j];
2947                   GC_BAMBOO_DEBUGPRINT_REG(objptr);
2948                   if(objptr != NULL) {
2949 #ifdef GC_TBL_DEBUG
2950                         void * dst = flushObj(objptr, __LINE__, ptr, j);
2951 #else
2952                         void * dst = flushObj(objptr);
2953 #endif
2954                         if(dst != NULL) {
2955                           ((void **)(((char *)&ao->___length___)+sizeof(int)))[j] = dst;
2956                         }
2957                   }
2958                 }
2959                 /* check the ArrayObject struct first*/
2960                 {
2961                   pointer=pointerarray[OBJECTTYPE];
2962                   //handle object class
2963                   unsigned int size=pointer[0];
2964                   int i;
2965                   for(i=1; i<=size; i++) {
2966                         unsigned int offset=pointer[i];
2967                         void * objptr=*((void **)(((char *)ao)+offset));
2968                         GC_BAMBOO_DEBUGPRINT_REG(objptr);
2969                         if(objptr != NULL) {
2970 #ifdef GC_TBL_DEBUG
2971                           void * dst = flushObj(objptr, __LINE__, ptr, j);
2972 #else
2973                           void * dst = flushObj(objptr);
2974 #endif
2975                           if(dst != NULL) {
2976                                 *((void **)(((char *)ao)+offset)) = dst;
2977                           }
2978                         }
2979                   }
2980                 }
2981       } else {
2982                 GC_BAMBOO_DEBUGPRINT(0xe30e);
2983                 unsigned int size=pointer[0];
2984                 int i;
2985                 for(i=1; i<=size; i++) {
2986                   GC_BAMBOO_DEBUGPRINT(0xe30f);
2987                   unsigned int offset=pointer[i];
2988                   void * objptr=*((void **)(((char *)ptr)+offset));
2989
2990                   GC_BAMBOO_DEBUGPRINT_REG(objptr);
2991                   if(objptr != NULL) {
2992 #ifdef GC_TBL_DEBUG
2993                         void * dst = flushObj(objptr, __LINE__, ptr, i);
2994 #else
2995                         void * dst = flushObj(objptr);
2996 #endif
2997                         if(dst != NULL) {
2998                           *((void **)(((char *)ptr)+offset)) = dst;
2999                         }
3000                   }
3001                 }  // for(i=1; i<=size; i++)
3002       }  // if (pointer==0) else if (((INTPTR)pointer)==1) else ()
3003       // restore the mark field, indicating that this obj has been flushed
3004       ((int *)(ptr))[BAMBOOMARKBIT] = INIT;
3005     }     // if(((int *)(ptr))[BAMBOOMARKBIT] == COMPACTED)
3006   }     // while(gc_lobjmoreItems())
3007   GC_BAMBOO_DEBUGPRINT(0xe310);
3008
3009   // send flush finish message to core coordinator
3010   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
3011     gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
3012   } else {
3013     send_msg_2(STARTUPCORE, GCFINISHFLUSH, BAMBOO_NUM_OF_CORE, false);
3014   }
3015   GC_BAMBOO_DEBUGPRINT(0xe311);
3016 } // flush()
3017
3018 #ifdef GC_CACHE_ADAPT
3019 // prepare for cache adaption:
3020 //   -- flush the shared heap
3021 //   -- clean dtlb entries
3022 //   -- change cache strategy
3023 void cacheAdapt_gc(bool isgccachestage) {
3024   // flush the shared heap
3025   BAMBOO_CACHE_FLUSH_L2();
3026
3027   // clean the dtlb entries
3028   BAMBOO_CLEAN_DTLB();
3029
3030   // change the cache strategy
3031   gccachestage = isgccachestage;
3032 } // cacheAdapt_gc(bool isgccachestage)
3033
3034 // the master core decides how to adapt cache strategy for the mutator 
3035 // according to collected statistic data
3036
3037 // make all pages hfh
3038 int cacheAdapt_policy_h4h(){
3039   unsigned int page_index = 0;
3040   VA page_sva = 0;
3041   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3042   int numchanged = 0;
3043   int * tmp_p = gccachepolicytbl+1;
3044   for(page_index = 0; page_index < page_num; page_index++) {
3045         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3046         bamboo_cache_policy_t policy = {0};
3047         policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
3048         *tmp_p = page_index;
3049         tmp_p++;
3050         *tmp_p = policy.word;
3051         tmp_p++;
3052         numchanged++;
3053   }
3054
3055   return numchanged;
3056 } // int cacheAdapt_policy_hfh()
3057
3058 // make all pages local as non-cache-adaptable gc local mode
3059 int cacheAdapt_policy_local(){
3060   unsigned int page_index = 0;
3061   VA page_sva = 0;
3062   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3063   int numchanged = 0;
3064   int * tmp_p = gccachepolicytbl+1;
3065   for(page_index = 0; page_index < page_num; page_index++) {
3066         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3067         bamboo_cache_policy_t policy = {0};
3068         unsigned int block = 0;
3069         BLOCKINDEX(page_sva, &block);
3070         unsigned int coren = gc_block2core[block%(NUMCORES4GC*2)];
3071         // locally cache the page in the hotest core
3072         // NOTE: (x,y) should be changed to (x+1, y+1)!!!
3073         policy.cache_mode = BAMBOO_CACHE_MODE_COORDS;
3074         policy.lotar_x = bamboo_cpu2coords[2*coren]+1;
3075         policy.lotar_y = bamboo_cpu2coords[2*coren+1]+1;
3076         *tmp_p = page_index;
3077         tmp_p++;
3078         *tmp_p = policy.word;
3079         tmp_p++;
3080         numchanged++;
3081   }
3082
3083   return numchanged;
3084 } // int cacheAdapt_policy_local()
3085
3086 int cacheAdapt_policy_hotest(){
3087   unsigned int page_index = 0;
3088   VA page_sva = 0;
3089   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3090   int numchanged = 0;
3091   int * tmp_p = gccachepolicytbl+1;
3092   for(page_index = 0; page_index < page_num; page_index++) {
3093         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3094         bamboo_cache_policy_t policy = {0};
3095         unsigned int hotestcore = 0;
3096         unsigned int hotfreq = 0;
3097
3098         unsigned int *local_tbl=&gccachesamplingtbl_r[page_index];
3099         for(int i = 0; i < NUMCORESACTIVE; i++) {
3100           unsigned int freq = *local_tbl;
3101           local_tbl=(unsigned int *)(
3102                   ((char *)local_tbl)+size_cachesamplingtbl_local_r);
3103
3104           // check the freqency, decide if this page is hot for the core
3105           if(hotfreq < freq) {
3106                 hotfreq = freq;
3107                 hotestcore = i;
3108           }
3109         }
3110         // TODO
3111         // Decide the cache strategy for this page
3112         // If decide to adapt a new cache strategy, write into the shared block of
3113         // the gcsharedsamplingtbl. The mem recording information that has been 
3114         // written is enough to hold the information.
3115         // Format: page start va + cache strategy(hfh/(host core+[x,y]))
3116         if(hotfreq == 0) {
3117           // this page has not been accessed, do not change its cache policy
3118           continue;
3119         } else {
3120           // locally cache the page in the hotest core
3121           // NOTE: (x,y) should be changed to (x+1, y+1)!!!
3122           policy.cache_mode = BAMBOO_CACHE_MODE_COORDS;
3123           policy.lotar_x = bamboo_cpu2coords[2*hotestcore]+1;
3124           policy.lotar_y = bamboo_cpu2coords[2*hotestcore+1]+1;
3125           *tmp_p = page_index;
3126           tmp_p++;
3127           *tmp_p = policy.word;
3128           tmp_p++;
3129           numchanged++;
3130         }
3131   }
3132
3133   return numchanged;
3134 } // int cacheAdapt_policy_hotest()
3135
3136 #define GC_CACHE_ADAPT_DOMINATE_THRESHOLD  50
3137 // cache the page on the core that accesses it the most if that core accesses 
3138 // it more than (GC_CACHE_ADAPT_DOMINATE_THRESHOLD)% of the total.  Otherwise,
3139 // h4h the page.
3140 int cacheAdapt_policy_dominate(){
3141   unsigned int page_index = 0;
3142   VA page_sva = 0;
3143   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3144   int numchanged = 0;
3145   int * tmp_p = gccachepolicytbl+1;
3146   for(page_index = 0; page_index < page_num; page_index++) {
3147         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3148         bamboo_cache_policy_t policy = {0};
3149         unsigned int hotestcore = 0;
3150         unsigned long long totalfreq = 0;
3151         unsigned int hotfreq = 0;
3152         
3153         unsigned int *local_tbl=&gccachesamplingtbl_r[page_index];
3154         for(int i = 0; i < NUMCORESACTIVE; i++) {
3155           unsigned int freq = *local_tbl;
3156           local_tbl=(unsigned int *)(
3157                   ((char *)local_tbl)+size_cachesamplingtbl_local_r);
3158           totalfreq += freq;
3159           // check the freqency, decide if this page is hot for the core
3160           if(hotfreq < freq) {
3161                 hotfreq = freq;
3162                 hotestcore = i;
3163           }
3164         }
3165
3166         // Decide the cache strategy for this page
3167         // If decide to adapt a new cache strategy, write into the shared block of
3168         // the gcpolicytbl 
3169         // Format: page start va + cache policy
3170         if(hotfreq == 0) {
3171           // this page has not been accessed, do not change its cache policy
3172           continue;
3173         }
3174         totalfreq = 
3175           (totalfreq*GC_CACHE_ADAPT_DOMINATE_THRESHOLD)/100/BAMBOO_PAGE_SIZE;
3176         hotfreq/=BAMBOO_PAGE_SIZE;
3177         if(hotfreq < totalfreq) {
3178           // use hfh
3179           policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
3180         } else {
3181           // locally cache the page in the hotest core
3182           // NOTE: (x,y) should be changed to (x+1, y+1)!!!
3183           policy.cache_mode = BAMBOO_CACHE_MODE_COORDS;
3184           policy.lotar_x = bamboo_cpu2coords[2*hotestcore]+1;
3185           policy.lotar_y = bamboo_cpu2coords[2*hotestcore+1]+1;
3186         }
3187         *tmp_p = page_index;
3188         tmp_p++;
3189         *tmp_p = policy.word;
3190         tmp_p++;
3191         numchanged++;
3192   }
3193
3194   return numchanged;
3195 } // int cacheAdapt_policy_dominate()
3196
3197 #define GC_CACHE_ADAPT_OVERLOAD_THRESHOLD 10
3198
3199 void gc_quicksort(unsigned long long *array, 
3200                       int left,
3201                                   int right,
3202                                   int offset) {
3203   int pivot = 0;;
3204   int leftIdx = left;
3205   int rightIdx = right;
3206   if((right-left+1) >= 1) {
3207         pivot = (left+right)/2;
3208         while((leftIdx <= pivot) && (rightIdx >= pivot)) {
3209           int pivotValue = array[pivot*3-offset];
3210           while((array[leftIdx*3-offset] > pivotValue) && (leftIdx <= pivot)) {
3211                 leftIdx++;
3212           }
3213           while((array[rightIdx*3-offset] < pivotValue) && (rightIdx >= pivot)) {
3214                 rightIdx--;
3215           }
3216           // swap [leftIdx] & [rightIdx]
3217           for(int k = 0; k < 3; k++) {
3218                 unsigned long long tmp = array[3*rightIdx-k];
3219                 array[3*rightIdx-k] = array[3*leftIdx-k];
3220                 array[3*leftIdx-k] = tmp;
3221           }
3222           leftIdx++;
3223           rightIdx--;
3224           if((leftIdx-1) == pivot) {
3225                 pivot = rightIdx = rightIdx + 1;
3226           } else if((leftIdx+1) == pivot) {
3227                 pivot = leftIdx = leftIdx-1;
3228           }
3229         }
3230         gc_quicksort(array, left, pivot-1, offset);
3231         gc_quicksort(array, pivot+1, right, offset);
3232   }
3233   return;
3234 } // void gc_quicksort(...)
3235
3236 // Every page cached on the core that accesses it the most. 
3237 // Check to see if any core's pages total more accesses than threshold 
3238 // GC_CACHE_ADAPT_OVERLOAD_THRESHOLD.  If so, find the pages with the 
3239 // most remote accesses and hash for home them until we get below 
3240 // GC_CACHE_ADAPT_OVERLOAD_THRESHOLD
3241 int cacheAdapt_policy_overload(){
3242   unsigned int page_index = 0;
3243   VA page_sva = 0;
3244   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3245   int numchanged = 0;
3246   int * tmp_p = gccachepolicytbl+1;
3247   unsigned long long workload[NUMCORESACTIVE];
3248   memset(workload, 0, NUMCORESACTIVE*sizeof(unsigned long long));
3249   unsigned long long total_workload = 0;
3250   unsigned long long core2heavypages[NUMCORESACTIVE][page_num*3+1];
3251   memset(core2heavypages,0,
3252           sizeof(unsigned long long)*(page_num*3+1)*NUMCORESACTIVE);
3253   for(page_index = 0; page_index < page_num; page_index++) {
3254         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3255         bamboo_cache_policy_t policy = {0};
3256         unsigned int hotestcore = 0;
3257         unsigned long long totalfreq = 0;
3258         unsigned int hotfreq = 0;
3259         
3260         unsigned int *local_tbl=&gccachesamplingtbl_r[page_index];
3261         for(int i = 0; i < NUMCORESACTIVE; i++) {
3262           unsigned int freq = *local_tbl;
3263           local_tbl=(unsigned int *)(
3264                   ((char *)local_tbl)+size_cachesamplingtbl_local_r);
3265           totalfreq += freq;
3266           // check the freqency, decide if this page is hot for the core
3267           if(hotfreq < freq) {
3268                 hotfreq = freq;
3269                 hotestcore = i;
3270           }
3271         }
3272         // Decide the cache strategy for this page
3273         // If decide to adapt a new cache strategy, write into the shared block of
3274         // the gcsharedsamplingtbl. The mem recording information that has been 
3275         // written is enough to hold the information.
3276         // Format: page start va + cache strategy(hfh/(host core+[x,y]))
3277         if(hotfreq == 0) {
3278           // this page has not been accessed, do not change its cache policy
3279           continue;
3280         }
3281
3282         totalfreq/=BAMBOO_PAGE_SIZE;
3283         hotfreq/=BAMBOO_PAGE_SIZE;
3284         // locally cache the page in the hotest core
3285         // NOTE: (x,y) should be changed to (x+1, y+1)!!!
3286         policy.cache_mode = BAMBOO_CACHE_MODE_COORDS;
3287         policy.lotar_x = bamboo_cpu2coords[2*hotestcore]+1;
3288         policy.lotar_y = bamboo_cpu2coords[2*hotestcore+1]+1;
3289         *tmp_p = page_index;
3290         tmp_p++;
3291         *tmp_p = policy.word;
3292         tmp_p++;
3293         numchanged++;
3294         workload[hotestcore] += totalfreq;
3295         total_workload += totalfreq;
3296         // insert into core2heavypages using quicksort
3297         unsigned long long remoteaccess = totalfreq - hotfreq;
3298         int index = (int)core2heavypages[hotestcore][0];
3299         core2heavypages[hotestcore][3*index+3] = remoteaccess;
3300         core2heavypages[hotestcore][3*index+2] = totalfreq;
3301         core2heavypages[hotestcore][3*index+1] = (unsigned long long)(tmp_p-1);
3302         core2heavypages[hotestcore][0]++;
3303   }
3304
3305   unsigned long long workload_threshold = 
3306         total_workload/GC_CACHE_ADAPT_OVERLOAD_THRESHOLD;
3307   // Check the workload of each core
3308   for(int i = 0; i < NUMCORESACTIVE; i++) {
3309         int j = 1;
3310         int index = (int)core2heavypages[i][0];
3311         if(workload[i] > workload_threshold) {
3312           // sort according to the remoteaccess
3313           gc_quicksort(&core2heavypages[i][0], 1, index, 0);
3314           while((workload[i] > workload_threshold) && (j<index*3)) {
3315                 // hfh those pages with more remote accesses 
3316                 bamboo_cache_policy_t policy = {0};
3317                 policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
3318                 *((int*)core2heavypages[i][j]) = policy.word;
3319                 workload[i] -= core2heavypages[i][j+1];
3320                 j += 3;
3321           }
3322         }
3323   }
3324
3325   return numchanged;
3326 } // int cacheAdapt_policy_overload()
3327
3328 #define GC_CACHE_ADAPT_ACCESS_THRESHOLD 70
3329 #define GC_CACHE_ADAPT_CROWD_THRESHOLD  20
3330 // Every page cached on the core that accesses it the most. 
3331 // Check to see if any core's pages total more accesses than threshold 
3332 // GC_CACHE_ADAPT_OVERLOAD_THRESHOLD.  If so, find the pages with the 
3333 // most remote accesses and hash for home them until we get below 
3334 // GC_CACHE_ADAPT_OVERLOAD_THRESHOLD.  
3335 // Sort pages based on activity.... 
3336 // If more then GC_CACHE_ADAPT_ACCESS_THRESHOLD% of the accesses for a
3337 // core's pages are from more than GC_CACHE_ADAPT_CROWD_THRESHOLD pages, 
3338 // then start hfh these pages(selecting the ones with the most remote 
3339 // accesses first or fewest local accesses) until we get below 
3340 // GC_CACHE_ADAPT_CROWD_THRESHOLD pages.
3341 int cacheAdapt_policy_crowd(){
3342   unsigned int page_index = 0;
3343   VA page_sva = 0;
3344   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3345   int numchanged = 0;
3346   int * tmp_p = gccachepolicytbl+1;
3347   unsigned long long workload[NUMCORESACTIVE];
3348   memset(workload, 0, NUMCORESACTIVE*sizeof(unsigned long long));
3349   unsigned long long total_workload = 0;
3350   unsigned long long core2heavypages[NUMCORESACTIVE][page_num*3+1];
3351   memset(core2heavypages,0,
3352           sizeof(unsigned long long)*(page_num*3+1)*NUMCORESACTIVE);
3353   for(page_index = 0; page_index < page_num; page_index++) {
3354         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3355         bamboo_cache_policy_t policy = {0};
3356         unsigned int hotestcore = 0;
3357         unsigned long long totalfreq = 0;
3358         unsigned int hotfreq = 0;
3359         
3360         unsigned int *local_tbl=&gccachesamplingtbl_r[page_index];
3361         for(int i = 0; i < NUMCORESACTIVE; i++) {
3362           unsigned int freq = *local_tbl;
3363           local_tbl=(unsigned int *)(
3364                   ((char *)local_tbl)+size_cachesamplingtbl_local_r);
3365           totalfreq += freq;
3366           // check the freqency, decide if this page is hot for the core
3367           if(hotfreq < freq) {
3368                 hotfreq = freq;
3369                 hotestcore = i;
3370           }
3371         }
3372         // Decide the cache strategy for this page
3373         // If decide to adapt a new cache strategy, write into the shared block of
3374         // the gcsharedsamplingtbl. The mem recording information that has been 
3375         // written is enough to hold the information.
3376         // Format: page start va + cache strategy(hfh/(host core+[x,y]))
3377         if(hotfreq == 0) {
3378           // this page has not been accessed, do not change its cache policy
3379           continue;
3380         }
3381         totalfreq/=BAMBOO_PAGE_SIZE;
3382         hotfreq/=BAMBOO_PAGE_SIZE;
3383         // locally cache the page in the hotest core
3384         // NOTE: (x,y) should be changed to (x+1, y+1)!!!
3385         policy.cache_mode = BAMBOO_CACHE_MODE_COORDS;
3386         policy.lotar_x = bamboo_cpu2coords[2*hotestcore]+1;
3387         policy.lotar_y = bamboo_cpu2coords[2*hotestcore+1]+1;
3388         *tmp_p = page_index;
3389         tmp_p++;
3390         *tmp_p = policy.word;
3391         tmp_p++;
3392         numchanged++;
3393         workload[hotestcore] += totalfreq;
3394         total_workload += totalfreq;
3395         // insert into core2heavypages using quicksort
3396         unsigned long long remoteaccess = totalfreq - hotfreq;
3397         int index = (int)core2heavypages[hotestcore][0];
3398         core2heavypages[hotestcore][3*index+3] = remoteaccess;
3399         core2heavypages[hotestcore][3*index+2] = totalfreq;
3400         core2heavypages[hotestcore][3*index+1] = (unsigned long long)(tmp_p-1);
3401         core2heavypages[hotestcore][0]++;
3402   }
3403
3404   unsigned long long workload_threshold = 
3405         total_workload / GC_CACHE_ADAPT_OVERLOAD_THRESHOLD;
3406   // Check the workload of each core
3407   for(int i = 0; i < NUMCORESACTIVE; i++) {
3408         int j = 1;
3409         int index = (int)core2heavypages[i][0];
3410         if(workload[i] > workload_threshold) {
3411           // sort according to the remoteaccess
3412           gc_quicksort(&core2heavypages[i][0], 1, index, 0);
3413           while((workload[i] > workload_threshold) && (j<index*3)) {
3414                 // hfh those pages with more remote accesses 
3415                 bamboo_cache_policy_t policy = {0};
3416                 policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
3417                 *((int*)core2heavypages[i][j]) = policy.word;
3418                 workload[i] -= core2heavypages[i][j+1];
3419                 j += 3;
3420           }
3421         }
3422
3423         // Check if the accesses are crowded on few pages
3424         // sort according to the total access
3425 inner_crowd:
3426         gc_quicksort(&core2heavypages[i][0], j/3+1, index, 1);
3427         unsigned long long threshold = 
3428           GC_CACHE_ADAPT_ACCESS_THRESHOLD*workload[i]/100;
3429         int num_crowded = 0;
3430         unsigned long long t_workload = 0;
3431         do {
3432           t_workload += core2heavypages[i][j+num_crowded*3+1];
3433           num_crowded++;
3434         } while(t_workload < threshold);
3435         // num_crowded <= GC_CACHE_ADAPT_CROWD_THRESHOLD and if there are enough 
3436         // items, it is always == GC_CACHE_ADAPT_CROWD_THRESHOLD
3437         if(num_crowded > GC_CACHE_ADAPT_CROWD_THRESHOLD) {
3438           // need to hfh these pages
3439           // sort the pages according to remote access
3440           gc_quicksort(&core2heavypages[i][0], j/3+1, j/3+num_crowded, 0);
3441           // h4h those pages with more remote accesses 
3442           bamboo_cache_policy_t policy = {0};
3443           policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
3444           *((int*)core2heavypages[i][j]) = policy.word;
3445           workload[i] -= core2heavypages[i][j+1];
3446           t_workload -= core2heavypages[i][j+1];
3447           j += 3;
3448           threshold = GC_CACHE_ADAPT_ACCESS_THRESHOLD*workload[i]/100;
3449           goto inner_crowd;
3450         }
3451   }
3452
3453   return numchanged;
3454 } // int cacheAdapt_policy_overload()
3455
3456 void cacheAdapt_master() {
3457 #ifdef GC_CACHE_ADAPT_SAMPLING_OUTPUT
3458   gc_output_cache_sampling_r();
3459 #endif // GC_CACHE_ADAPT_SAMPLING_OUTPUT
3460   int numchanged = 0;
3461   // check the statistic data
3462   // for each page, decide the new cache strategy
3463 #ifdef GC_CACHE_ADAPT_POLICY1
3464   numchanged = cacheAdapt_policy_h4h();
3465 #elif defined GC_CACHE_ADAPT_POLICY2
3466   numchanged = cacheAdapt_policy_local();
3467 #elif defined GC_CACHE_ADAPT_POLICY3
3468   numchanged = cacheAdapt_policy_hotest();
3469 #elif defined GC_CACHE_ADAPT_POLICY4
3470   numchanged = cacheAdapt_policy_dominate();
3471 #elif defined GC_CACHE_ADAPT_POLICY5
3472   numchanged = cacheAdapt_policy_overload();
3473 #elif defined GC_CACHE_ADAPT_POLICY6
3474   numchanged = cacheAdapt_policy_crowd();
3475 #endif
3476   *gccachepolicytbl = numchanged;
3477 }
3478
3479 // adapt the cache strategy for the mutator
3480 void cacheAdapt_mutator() {
3481   int numchanged = *gccachepolicytbl;
3482   // check the changes and adapt them
3483   int * tmp_p = gccachepolicytbl+1;
3484   while(numchanged--) {
3485         // read out the policy
3486         int page_index = *tmp_p;
3487         bamboo_cache_policy_t policy = (bamboo_cache_policy_t)(*(tmp_p+1));
3488         // adapt the policy
3489         bamboo_adapt_cache_policy(page_index*(BAMBOO_PAGE_SIZE)+gcbaseva, 
3490                 policy, BAMBOO_PAGE_SIZE);
3491
3492         tmp_p += 2;
3493   }
3494 }
3495
3496 void gc_output_cache_sampling() {
3497   unsigned int page_index = 0;
3498   VA page_sva = 0;
3499   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3500   for(page_index = 0; page_index < page_num; page_index++) {
3501         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3502         unsigned int block = 0;
3503         BLOCKINDEX(page_sva, &block);
3504         int coren = gc_block2core[block%(NUMCORES4GC*2)];
3505         tprintf("va: %x page_index: %d host: %d\n", 
3506                 (int)page_sva, page_index, coren);
3507         for(int i = 0; i < NUMCORESACTIVE; i++) {
3508           unsigned int * local_tbl = (unsigned int *)((void *)gccachesamplingtbl
3509                   +size_cachesamplingtbl_local*i);
3510           unsigned int freq = local_tbl[page_index];
3511           printf("%8d ",freq);
3512         }
3513         printf("\n");
3514   }
3515   printf("=================\n");
3516 } // gc_output_cache_sampling
3517
3518 void gc_output_cache_sampling_r() {
3519   unsigned int page_index = 0;
3520   VA page_sva = 0;
3521   unsigned int page_num = (BAMBOO_SHARED_MEM_SIZE) / (BAMBOO_PAGE_SIZE);
3522   for(page_index = 0; page_index < page_num; page_index++) {
3523         page_sva = gcbaseva + (BAMBOO_PAGE_SIZE) * page_index;
3524         unsigned int block = 0;
3525         BLOCKINDEX(page_sva, &block);
3526         int coren = gc_block2core[block%(NUMCORES4GC*2)];
3527         tprintf("va: %x page_index: %d host: %d\n", 
3528                 (int)page_sva, page_index, coren);
3529         for(int i = 0; i < NUMCORESACTIVE; i++) {
3530           unsigned int * local_tbl = (unsigned int *)((void *)gccachesamplingtbl_r
3531                   +size_cachesamplingtbl_local_r*i);
3532           unsigned int freq = local_tbl[page_index]/BAMBOO_PAGE_SIZE;
3533           printf("%8d ",freq);
3534         }
3535         printf("\n");
3536   }
3537   printf("=================\n");
3538 } // gc_output_cache_sampling
3539 #endif // GC_CACHE_ADAPT
3540
3541 inline void gc_collect(struct garbagelist * stackptr) {
3542   // inform the master that this core is at a gc safe point and is ready to 
3543   // do gc
3544   send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, self_numsendobjs, 
3545           self_numreceiveobjs, false);
3546
3547   // core collector routine
3548   while(true) {
3549     if(INITPHASE == gcphase) {
3550       break;
3551     }
3552   }
3553 #ifdef RAWPATH // TODO GC_DEBUG
3554   printf("(%X,%X) Do initGC\n", udn_tile_coord_x(), udn_tile_coord_y());
3555 #endif
3556   initGC();
3557 #ifdef GC_CACHE_ADAPT
3558   // prepare for cache adaption:
3559   cacheAdapt_gc(true);
3560 #endif // GC_CACHE_ADAPT
3561   //send init finish msg to core coordinator
3562   send_msg_2(STARTUPCORE, GCFINISHINIT, BAMBOO_NUM_OF_CORE, false);
3563
3564   while(true) {
3565     if(MARKPHASE == gcphase) {
3566       break;
3567     }
3568   }
3569 #ifdef RAWPATH // TODO GC_DEBUG
3570   printf("(%x,%x) Start mark phase\n", udn_tile_coord_x(), 
3571              udn_tile_coord_y());
3572 #endif
3573   mark(true, stackptr);
3574 #ifdef RAWPATH // TODO GC_DEBUG
3575   printf("(%x,%x) Finish mark phase, start compact phase\n", 
3576              udn_tile_coord_x(), udn_tile_coord_y());
3577 #endif
3578   compact();
3579 #ifdef RAWPATH // TODO GC_DEBUG
3580   printf("(%x,%x) Finish compact phase\n", udn_tile_coord_x(),
3581              udn_tile_coord_y());
3582 #endif
3583
3584   while(true) {
3585     if(FLUSHPHASE == gcphase) {
3586       break;
3587     }
3588   }
3589 #ifdef RAWPATH // TODO GC_DEBUG
3590   printf("(%x,%x) Start flush phase\n", udn_tile_coord_x(), 
3591              udn_tile_coord_y());
3592 #endif
3593 #ifdef GC_PROFILE
3594   // send the num of obj/liveobj/forwardobj to the startupcore
3595   if(STARTUPCORE != BAMBOO_NUM_OF_CORE) {
3596         send_msg_4(STARTUPCORE, GCPROFILES, gc_num_obj, 
3597                 gc_num_liveobj, gc_num_forwardobj, false);
3598   }
3599   gc_num_obj = 0;
3600 #endif // GC_PROFLIE
3601   flush(stackptr);
3602 #ifdef RAWPATH // TODO GC_DEBUG
3603   printf("(%x,%x) Finish flush phase\n", udn_tile_coord_x(),
3604              udn_tile_coord_y());
3605 #endif
3606
3607 #ifdef GC_CACHE_ADAPT
3608   while(true) {
3609     if(PREFINISHPHASE == gcphase) {
3610       break;
3611     }
3612   }
3613 #ifdef RAWPATH // TODO GC_DEBUG
3614   printf("(%x,%x) Start prefinish phase\n", udn_tile_coord_x(), 
3615              udn_tile_coord_y());
3616 #endif
3617   // cache adapt phase
3618   cacheAdapt_mutator();
3619   cacheAdapt_gc(false);
3620   //send init finish msg to core coordinator
3621   send_msg_2(STARTUPCORE, GCFINISHPREF, BAMBOO_NUM_OF_CORE, false);
3622 #ifdef RAWPATH // TODO GC_DEBUG
3623   printf("(%x,%x) Finish prefinish phase\n", udn_tile_coord_x(),
3624              udn_tile_coord_y());
3625 #endif
3626 #ifdef GC_CACHE_SAMPLING
3627   // reset the sampling arrays
3628   bamboo_dtlb_sampling_reset();
3629 #endif // GC_CACHE_SAMPLING
3630   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
3631         // zero out the gccachesamplingtbl
3632         BAMBOO_MEMSET_WH(gccachesamplingtbl_local,0,size_cachesamplingtbl_local);
3633         BAMBOO_MEMSET_WH(gccachesamplingtbl_local_r,0,
3634                 size_cachesamplingtbl_local_r);
3635   }
3636 #endif // GC_CACHE_ADAPT
3637
3638   // invalidate all shared mem pointers
3639   bamboo_cur_msp = NULL;
3640   bamboo_smem_size = 0;
3641   bamboo_smem_zero_top = NULL;
3642
3643   while(true) {
3644     if(FINISHPHASE == gcphase) {
3645       break;
3646     }
3647   }
3648
3649   //gcflag = false;
3650   //gcprocessing = false;
3651 #ifdef RAWPATH // TODO GC_DEBUG
3652   printf("(%x,%x) Finish gc! \n", udn_tile_coord_x(), udn_tile_coord_y());
3653 #endif
3654 } // void gc_collect(struct garbagelist * stackptr)
3655
3656 inline void gc_nocollect(struct garbagelist * stackptr) {
3657   // inform the master that this core is at a gc safe point and is ready to 
3658   // do gc
3659   send_msg_4(STARTUPCORE, GCFINISHPRE, BAMBOO_NUM_OF_CORE, self_numsendobjs, 
3660           self_numreceiveobjs, false);
3661   
3662   while(true) {
3663     if(INITPHASE == gcphase) {
3664       break;
3665     }
3666   }
3667 #ifdef RAWPATH // TODO GC_DEBUG
3668   printf("(%x,%x) Do initGC\n", udn_tile_coord_x(), udn_tile_coord_y());
3669 #endif
3670   initGC();
3671 #ifdef GC_CACHE_ADAPT
3672   // prepare for cache adaption:
3673   cacheAdapt_gc(true);
3674 #endif // GC_CACHE_ADAPT
3675   //send init finish msg to core coordinator
3676   send_msg_2(STARTUPCORE, GCFINISHINIT, BAMBOO_NUM_OF_CORE, false);
3677
3678   while(true) {
3679     if(MARKPHASE == gcphase) {
3680       break;
3681     }
3682   }
3683 #ifdef RAWPATH // TODO GC_DEBUG
3684   printf("(%x,%x) Start mark phase\n", udn_tile_coord_x(), 
3685              udn_tile_coord_y());
3686 #endif
3687   mark(true, stackptr);
3688 #ifdef RAWPATH // TODO GC_DEBUG
3689   printf("(%x,%x) Finish mark phase, wait for flush\n", 
3690              udn_tile_coord_x(), udn_tile_coord_y());
3691 #endif
3692
3693   // non-gc core collector routine
3694   while(true) {
3695     if(FLUSHPHASE == gcphase) {
3696       break;
3697     }
3698   }
3699 #ifdef RAWPATH // TODO GC_DEBUG
3700   printf("(%x,%x) Start flush phase\n", udn_tile_coord_x(), 
3701              udn_tile_coord_y());
3702 #endif
3703 #ifdef GC_PROFILE
3704   if(STARTUPCORE != BAMBOO_NUM_OF_CORE) {
3705         send_msg_4(STARTUPCORE, GCPROFILES, gc_num_obj, 
3706                 gc_num_liveobj, gc_num_forwardobj, false);
3707   }
3708   gc_num_obj = 0;
3709 #endif // GC_PROFLIE
3710   flush(stackptr);
3711 #ifdef RAWPATH // TODO GC_DEBUG
3712   printf("(%x,%x) Finish flush phase\n", udn_tile_coord_x(), 
3713              udn_tile_coord_y());
3714 #endif
3715
3716 #ifdef GC_CACHE_ADAPT
3717   while(true) {
3718     if(PREFINISHPHASE == gcphase) {
3719       break;
3720     }
3721   }
3722 #ifdef RAWPATH // TODO GC_DEBUG
3723   printf("(%x,%x) Start prefinish phase\n", udn_tile_coord_x(), 
3724              udn_tile_coord_y());
3725 #endif
3726   // cache adapt phase
3727   cacheAdapt_mutator();
3728   cacheAdapt_gc(false);
3729   //send init finish msg to core coordinator
3730   send_msg_2(STARTUPCORE, GCFINISHPREF, BAMBOO_NUM_OF_CORE, false);
3731 #ifdef RAWPATH // TODO GC_DEBUG
3732   printf("(%x,%x) Finish prefinish phase\n", udn_tile_coord_x(),
3733              udn_tile_coord_y());
3734 #endif
3735 #ifdef GC_CACHE_SAMPLING
3736   // reset the sampling arrays
3737   bamboo_dtlb_sampling_reset();
3738 #endif // GC_CACHE_SAMPLING
3739   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
3740         // zero out the gccachesamplingtbl
3741         BAMBOO_MEMSET_WH(gccachesamplingtbl_local,0,size_cachesamplingtbl_local);
3742         BAMBOO_MEMSET_WH(gccachesamplingtbl_local_r,0,
3743                 size_cachesamplingtbl_local_r);
3744   }
3745 #endif // GC_CACHE_ADAPT
3746
3747   // invalidate all shared mem pointers
3748   bamboo_cur_msp = NULL;
3749   bamboo_smem_size = 0;
3750   bamboo_smem_zero_top = NULL;
3751
3752   while(true) {
3753     if(FINISHPHASE == gcphase) {
3754       break;
3755     }
3756   }
3757   //gcflag = false;
3758   //gcprocessing = false;
3759 #ifdef RAWPATH // TODO GC_DEBUG
3760   printf("(%x,%x) Finish gc! \n", udn_tile_coord_x(), udn_tile_coord_y());
3761 #endif
3762 } // void gc_collect(struct garbagelist * stackptr)
3763
3764 inline void gc_master(struct garbagelist * stackptr) {
3765   //tprintf("start GC !!!!!!!!!!!!! \n");
3766
3767   gcphase = INITPHASE;
3768   int i = 0;
3769   waitconfirm = false;
3770   numconfirm = 0;
3771   initGC();
3772
3773   // Note: all cores need to init gc including non-gc cores
3774   for(i = 1; i < NUMCORESACTIVE /*NUMCORES4GC*/; i++) {
3775         // send GC init messages to all cores
3776         send_msg_1(i, GCSTARTINIT, false);
3777   }
3778   bool isfirst = true;
3779   bool allStall = false;
3780
3781 #ifdef GC_CACHE_ADAPT
3782   // prepare for cache adaption:
3783   cacheAdapt_gc(true);
3784 #endif // GC_CACHE_ADAPT
3785
3786 #ifdef RAWPATH // TODO GC_DEBUG
3787   printf("(%x,%x) Check core status \n", udn_tile_coord_x(), 
3788                  udn_tile_coord_y());
3789 #endif
3790
3791   gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
3792   while(true) {
3793         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
3794         if(gc_checkAllCoreStatus_I()) {
3795           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3796           break;
3797         }
3798         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3799   }
3800 #ifdef GC_PROFILE
3801 #ifdef MGC_SPEC
3802         if(gc_profile_flag) {
3803 #endif
3804   gc_profileItem();
3805 #ifdef MGC_SPEC
3806         }
3807 #endif
3808 #endif
3809 #ifdef GC_CACHE_ADAPT_POLICY_OUTPUT
3810   gc_output_cache_sampling();
3811 #endif // GC_CACHE_ADAPT
3812 #ifdef RAWPATH // TODO GC_DEBUG
3813   printf("(%x,%x) Start mark phase \n", udn_tile_coord_x(), 
3814                  udn_tile_coord_y());
3815 #endif
3816   // restore the gcstatus of all cores
3817   // Note: all cores have to do mark including non-gc cores
3818   gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
3819   for(i = 1; i < NUMCORESACTIVE; ++i) {
3820         gccorestatus[i] = 1;
3821         // send GC start messages to all cores
3822         send_msg_1(i, GCSTART, false);
3823   }
3824
3825   gcphase = MARKPHASE;
3826   // mark phase
3827   while(MARKPHASE == gcphase) {
3828         mark(isfirst, stackptr);
3829         if(isfirst) {
3830           isfirst = false;
3831         }
3832
3833         // check gcstatus
3834         checkMarkStatue();
3835   }   // while(MARKPHASE == gcphase)
3836   // send msgs to all cores requiring large objs info
3837   // Note: only need to ask gc cores, non-gc cores do not host any objs
3838   numconfirm = NUMCORES4GC - 1;
3839   for(i = 1; i < NUMCORES4GC; ++i) {
3840         send_msg_1(i, GCLOBJREQUEST, false);
3841   }
3842   gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
3843   while(true) {
3844         if(numconfirm==0) {
3845           break;
3846         }
3847   }   // wait for responses
3848   // check the heaptop
3849   if(gcheaptop < gcmarkedptrbound) {
3850         gcheaptop = gcmarkedptrbound;
3851   }
3852 #ifdef GC_PROFILE
3853 #ifdef MGC_SPEC
3854         if(gc_profile_flag) {
3855 #endif
3856   gc_profileItem();
3857 #ifdef MGC_SPEC
3858         }
3859 #endif
3860 #endif
3861 #ifdef RAWPATH // TODO GC_DEBUG
3862   printf("(%x,%x) prepare to cache large objs \n", udn_tile_coord_x(),
3863                  udn_tile_coord_y());
3864 #endif
3865   // cache all large objs
3866   if(!cacheLObjs()) {
3867         // no enough space to cache large objs
3868         BAMBOO_EXIT(0xb02b);
3869   }
3870   // predict number of blocks to fill for each core
3871   unsigned int tmpheaptop = 0;
3872   int numpbc = loadbalance(&tmpheaptop);
3873   // TODO
3874   numpbc = (BAMBOO_SHARED_MEM_SIZE)/(BAMBOO_SMEM_SIZE);
3875 #ifdef RAWPATH // TODO GC_DEBUG
3876   printf("(%x,%x) mark phase finished \n", udn_tile_coord_x(), 
3877                  udn_tile_coord_y());
3878 #endif
3879   //int tmptopptr = 0;
3880   //BASEPTR(gctopcore, 0, &tmptopptr);
3881   // TODO
3882   //tmptopptr = gcbaseva + (BAMBOO_SHARED_MEM_SIZE);
3883   tmpheaptop = gcbaseva + (BAMBOO_SHARED_MEM_SIZE);
3884   GC_BAMBOO_DEBUGPRINT(0xabab);
3885   GC_BAMBOO_DEBUGPRINT_REG(tmpheaptop);
3886   for(i = 0; i < NUMCORES4GC; ++i) {
3887         unsigned int tmpcoreptr = 0;
3888         BASEPTR(i, numpbc, &tmpcoreptr);
3889         // init some data strutures for compact phase
3890         gcloads[i] = 0;
3891         gcfilledblocks[i] = 0;
3892         gcrequiredmems[i] = 0;
3893         gccorestatus[i] = 1;
3894         //send start compact messages to all cores
3895         //TODO bug here, do not know if the direction is positive or negtive?
3896         if (tmpcoreptr < tmpheaptop) {
3897           gcstopblock[i] = numpbc + 1;
3898           if(i != STARTUPCORE) {
3899                 send_msg_2(i, GCSTARTCOMPACT, numpbc+1, false);
3900           } else {
3901                 gcblock2fill = numpbc+1;
3902           }   // if(i != STARTUPCORE)
3903         } else {
3904           gcstopblock[i] = numpbc;
3905           if(i != STARTUPCORE) {
3906                 send_msg_2(i, GCSTARTCOMPACT, numpbc, false);
3907           } else {
3908                 gcblock2fill = numpbc;
3909           }  // if(i != STARTUPCORE)
3910         }
3911         GC_BAMBOO_DEBUGPRINT(0xf000+i);
3912         GC_BAMBOO_DEBUGPRINT_REG(tmpcoreptr);
3913         GC_BAMBOO_DEBUGPRINT_REG(gcstopblock[i]);
3914   }
3915
3916   BAMBOO_CACHE_MF();
3917
3918 #ifdef GC_PROFILE
3919 #ifdef MGC_SPEC
3920         if(gc_profile_flag) {
3921 #endif
3922   gc_profileItem();
3923 #ifdef MGC_SPEC
3924         }
3925 #endif
3926 #endif
3927
3928   // compact phase
3929   bool finalcompact = false;
3930   // initialize pointers for comapcting
3931   struct moveHelper * orig =
3932         (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
3933   struct moveHelper * to =
3934         (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
3935   initOrig_Dst(orig, to);
3936   int filledblocks = 0;
3937   unsigned int heaptopptr = 0;
3938   bool finishcompact = false;
3939   bool iscontinue = true;
3940   bool localcompact = true;
3941   while((COMPACTPHASE == gcphase) || (SUBTLECOMPACTPHASE == gcphase)) {
3942         if((!finishcompact) && iscontinue) {
3943           GC_BAMBOO_DEBUGPRINT(0xeaa01);
3944           GC_BAMBOO_DEBUGPRINT_REG(numpbc);
3945           GC_BAMBOO_DEBUGPRINT_REG(gcblock2fill);
3946           finishcompact = compacthelper(orig, to, &filledblocks,
3947                                                                         &heaptopptr, &localcompact);
3948           GC_BAMBOO_DEBUGPRINT(0xeaa02);
3949           GC_BAMBOO_DEBUGPRINT_REG(finishcompact);
3950           GC_BAMBOO_DEBUGPRINT_REG(gctomove);
3951           GC_BAMBOO_DEBUGPRINT_REG(gcrequiredmems[0]);
3952           GC_BAMBOO_DEBUGPRINT_REG(gcfilledblocks[0]);
3953           GC_BAMBOO_DEBUGPRINT_REG(gcstopblock[0]);
3954         }
3955
3956         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
3957         if(gc_checkCoreStatus_I()) {
3958           // all cores have finished compacting
3959           // restore the gcstatus of all cores
3960           for(i = 0; i < NUMCORES4GC; ++i) {
3961                 gccorestatus[i] = 1;
3962           }
3963           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3964           break;
3965         } else {
3966           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
3967           // check if there are spare mem for pending move requires
3968           if(COMPACTPHASE == gcphase) {
3969                 GC_BAMBOO_DEBUGPRINT(0xeaa03);
3970                 resolvePendingMoveRequest();
3971                 GC_BAMBOO_DEBUGPRINT_REG(gctomove);
3972           } else {
3973                 GC_BAMBOO_DEBUGPRINT(0xeaa04);
3974                 compact2Heaptop();
3975           }
3976         }   // if(gc_checkCoreStatus_I()) else ...
3977
3978         if(gctomove) {
3979           GC_BAMBOO_DEBUGPRINT(0xeaa05);
3980           GC_BAMBOO_DEBUGPRINT_REG(gcmovestartaddr);
3981           GC_BAMBOO_DEBUGPRINT_REG(gcblock2fill);
3982           GC_BAMBOO_DEBUGPRINT_REG(gctomove);
3983           to->ptr = gcmovestartaddr;
3984           to->numblocks = gcblock2fill - 1;
3985           to->bound = (to->numblocks==0) ?
3986                                   BAMBOO_SMEM_SIZE_L :
3987                                   BAMBOO_SMEM_SIZE_L+BAMBOO_SMEM_SIZE*to->numblocks;
3988           BASEPTR(gcdstcore, to->numblocks, &(to->base));
3989           to->offset = to->ptr - to->base;
3990           to->top = (to->numblocks==0) ?
3991                                 (to->offset) : (to->bound-BAMBOO_SMEM_SIZE+to->offset);
3992           to->base = to->ptr;
3993           to->offset = BAMBOO_CACHE_LINE_SIZE;
3994           to->ptr += to->offset;                         // for header
3995           to->top += to->offset;
3996           if(gcdstcore == BAMBOO_NUM_OF_CORE) {
3997                 localcompact = true;
3998           } else {
3999                 localcompact = false;
4000           }
4001           gctomove = false;
4002           iscontinue = true;
4003         } else if(!finishcompact) {
4004           // still pending
4005           iscontinue = false;
4006         }  // if(gctomove)
4007   }  // while(COMPACTPHASE == gcphase)
4008 #ifdef GC_PROFILE
4009 #ifdef MGC_SPEC
4010         if(gc_profile_flag) {
4011 #endif
4012   gc_profileItem();
4013 #ifdef MGC_SPEC
4014         }
4015 #endif
4016 #endif
4017 #ifdef RAWPATH // TODO GC_DEBUG
4018   printf("(%x,%x) prepare to move large objs \n", udn_tile_coord_x(),
4019                  udn_tile_coord_y());
4020 #endif
4021   // move largeObjs
4022   moveLObjs();
4023 #ifdef RAWPATH // TODO GC_DEBUG
4024   printf("(%x,%x) compact phase finished \n", udn_tile_coord_x(), 
4025                  udn_tile_coord_y());
4026 #endif
4027   RUNFREE(orig);
4028   RUNFREE(to);
4029   orig = to = NULL;
4030
4031   gcphase = FLUSHPHASE;
4032   gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
4033   // Note: all cores should flush their runtime data including non-gc
4034   //       cores
4035   for(i = 1; i < NUMCORESACTIVE; ++i) {
4036         // send start flush messages to all cores
4037         gccorestatus[i] = 1;
4038         send_msg_1(i, GCSTARTFLUSH, false);
4039   }
4040 #ifdef GC_PROFILE
4041 #ifdef MGC_SPEC
4042         if(gc_profile_flag) {
4043 #endif
4044   gc_profileItem();
4045 #ifdef MGC_SPEC
4046         }
4047 #endif
4048 #endif
4049 #ifdef RAWPATH // TODO GC_DEBUG
4050   printf("(%x,%x) Start flush phase \n", udn_tile_coord_x(), 
4051                  udn_tile_coord_y());
4052 #endif
4053   // flush phase
4054   flush(stackptr);
4055
4056 #ifdef GC_CACHE_ADAPT
4057   // now the master core need to decide the new cache strategy
4058   cacheAdapt_master();
4059 #endif // GC_CACHE_ADAPT
4060
4061   gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
4062   while(FLUSHPHASE == gcphase) {
4063         // check the status of all cores
4064         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
4065         if(gc_checkAllCoreStatus_I()) {
4066           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4067           break;
4068         }
4069         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4070   }  // while(FLUSHPHASE == gcphase)
4071 #ifdef RAWPATH // TODO GC_DEBUG
4072   printf("(%x,%x) Finish flush phase \n", udn_tile_coord_x(), 
4073                  udn_tile_coord_y());
4074 #endif
4075
4076 #ifdef GC_CACHE_ADAPT
4077 #ifdef GC_PROFILE
4078 #ifdef MGC_SPEC
4079         if(gc_profile_flag) {
4080 #endif
4081   gc_profileItem();
4082 #ifdef MGC_SPEC
4083         }
4084 #endif
4085 #endif
4086   gcphase = PREFINISHPHASE;
4087   gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
4088   // Note: all cores should flush their runtime data including non-gc
4089   //       cores
4090   for(i = 1; i < NUMCORESACTIVE; ++i) {
4091         // send start flush messages to all cores
4092         gccorestatus[i] = 1;
4093         send_msg_1(i, GCSTARTPREF, false);
4094   }
4095 #ifdef RAWPATH // TODO GC_DEBUG
4096   printf("(%x,%x) Start prefinish phase \n", udn_tile_coord_x(), 
4097                  udn_tile_coord_y());
4098 #endif
4099   // cache adapt phase
4100   cacheAdapt_mutator();
4101 #ifdef GC_CACHE_ADAPT_OUTPUT
4102   bamboo_output_cache_policy();
4103 #endif
4104   cacheAdapt_gc(false);
4105
4106   gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
4107   while(PREFINISHPHASE == gcphase) {
4108         // check the status of all cores
4109         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
4110         if(gc_checkAllCoreStatus_I()) {
4111           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4112           break;
4113         }
4114         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4115   }  // while(PREFINISHPHASE == gcphase)
4116
4117 #ifdef GC_CACHE_SAMPLING
4118   // reset the sampling arrays
4119   bamboo_dtlb_sampling_reset();
4120 #endif // GC_CACHE_SAMPLING
4121   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
4122         // zero out the gccachesamplingtbl
4123         BAMBOO_MEMSET_WH(gccachesamplingtbl_local,0,size_cachesamplingtbl_local);
4124         BAMBOO_MEMSET_WH(gccachesamplingtbl_local_r,0,
4125                 size_cachesamplingtbl_local_r);
4126         BAMBOO_MEMSET_WH(gccachepolicytbl,0,size_cachepolicytbl);
4127   }
4128 #endif // GC_CACHE_ADAPT
4129
4130   gcphase = FINISHPHASE;
4131
4132   // invalidate all shared mem pointers
4133   // put it here as it takes time to inform all the other cores to
4134   // finish gc and it might cause problem when some core resumes
4135   // mutator earlier than the other cores
4136   bamboo_cur_msp = NULL;
4137   bamboo_smem_size = 0;
4138   bamboo_smem_zero_top = NULL;
4139
4140 #ifdef GC_PROFILE
4141 #ifdef MGC_SPEC
4142         if(gc_profile_flag) {
4143 #endif
4144   gc_profileEnd();
4145 #ifdef MGC_SPEC
4146         }
4147 #endif
4148 #endif
4149   gccorestatus[BAMBOO_NUM_OF_CORE] = 1;
4150   for(i = 1; i < NUMCORESACTIVE; ++i) {
4151         // send gc finish messages to all cores
4152         send_msg_1(i, GCFINISH, false);
4153         gccorestatus[i] = 1;
4154   }
4155
4156   gcflag = false;
4157   gcprocessing = false;
4158 #ifdef RAWPATH // TODO GC_DEBUG
4159   printf("(%x,%x) gc finished   \n", udn_tile_coord_x(), 
4160                  udn_tile_coord_y());
4161 #endif
4162   //tprintf("finish GC ! \n");
4163 } // void gc_master(struct garbagelist * stackptr)
4164
4165 inline bool gc(struct garbagelist * stackptr) {
4166   // check if do gc
4167   if(!gcflag) {
4168     gcprocessing = false;
4169     return false;
4170   }
4171
4172 #ifdef GC_CACHE_ADAPT
4173 #ifdef GC_CACHE_SAMPLING
4174     // disable the timer interrupt
4175     bamboo_mask_timer_intr();
4176 #endif 
4177 #endif
4178   // core coordinator routine
4179   if(0 == BAMBOO_NUM_OF_CORE) {
4180 #ifdef GC_DEBUG
4181     printf("(%x,%x) Check if can do gc or not\n", udn_tile_coord_x(),
4182                    udn_tile_coord_y());
4183 #endif
4184         bool isallstall = true;
4185         gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
4186         BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
4187         int ti = 0;
4188         for(ti = 0; ti < NUMCORESACTIVE; ++ti) {
4189           if(gccorestatus[ti] != 0) {
4190                 isallstall = false;
4191                 break;
4192           }
4193         }
4194         if(!isallstall) {
4195           BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4196           // some of the cores are still executing the mutator and did not reach
4197           // some gc safe point, therefore it is not ready to do gc
4198           gcflag = true;
4199           return false;
4200         } else {
4201 #ifdef GC_PROFILE
4202 #ifdef MGC_SPEC
4203         if(gc_profile_flag) {
4204 #endif
4205     gc_profileStart();
4206 #ifdef MGC_SPEC
4207         }
4208 #endif
4209 #endif
4210 pregccheck:
4211           gcnumsendobjs[0][BAMBOO_NUM_OF_CORE] = self_numsendobjs;
4212           gcnumreceiveobjs[0][BAMBOO_NUM_OF_CORE] = self_numreceiveobjs;
4213           int sumsendobj = 0;
4214           GC_BAMBOO_DEBUGPRINT(0xec04);
4215           for(int i = 0; i < NUMCORESACTIVE; ++i) {
4216                 sumsendobj += gcnumsendobjs[0][i];
4217                 GC_BAMBOO_DEBUGPRINT(0xf000 + gcnumsendobjs[0][i]);
4218           }  // for(i = 1; i < NUMCORESACTIVE; ++i)
4219           GC_BAMBOO_DEBUGPRINT(0xec05);
4220           GC_BAMBOO_DEBUGPRINT_REG(sumsendobj);
4221           for(int i = 0; i < NUMCORESACTIVE; ++i) {
4222                 sumsendobj -= gcnumreceiveobjs[0][i];
4223                 GC_BAMBOO_DEBUGPRINT(0xf000 + gcnumreceiveobjs[i]);
4224           }  // for(i = 1; i < NUMCORESACTIVE; ++i)
4225           GC_BAMBOO_DEBUGPRINT(0xec06);
4226           GC_BAMBOO_DEBUGPRINT_REG(sumsendobj);
4227           if(0 != sumsendobj) {
4228                 // there were still some msgs on the fly, wait until there 
4229                 // are some update pregc information coming and check it again
4230                 gcprecheck = false;
4231                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4232                 while(true) {
4233                   if(gcprecheck) {
4234                         break;
4235                   }
4236                 }
4237                 goto pregccheck;
4238           } else {
4239                 BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
4240           }
4241         }
4242 #ifdef RAWPATH // TODO GC_DEBUG
4243     printf("(%x,%x) start gc! \n", udn_tile_coord_x(), udn_tile_coord_y());
4244 #endif
4245         // Zero out the remaining bamboo_cur_msp 
4246         // Only zero out the first 4 bytes of the remaining memory
4247         // Move the operation here because for the GC_CACHE_ADAPT version,
4248         // we need to make sure during the gcinit phase the shared heap is not 
4249         // touched. Otherwise, there would be problem when adapt the cache 
4250         // strategy.
4251         if((bamboo_cur_msp != 0) 
4252                 && (bamboo_smem_zero_top == bamboo_cur_msp) 
4253                 && (bamboo_smem_size > 0)) {
4254           *((int *)bamboo_cur_msp) = 0;
4255         }
4256 #ifdef GC_FLUSH_DTLB
4257         if(gc_num_flush_dtlb < GC_NUM_FLUSH_DTLB) {
4258           BAMBOO_CLEAN_DTLB();
4259           gc_num_flush_dtlb++;
4260         }
4261 #endif
4262 #ifdef GC_CACHE_ADAPT
4263 #ifdef GC_CACHE_SAMPLING
4264     // get the sampling data 
4265     bamboo_output_dtlb_sampling();
4266 #endif // GC_CACHE_SAMPLING
4267 #endif // GC_CACHE_ADAPT
4268         gcprocessing = true;
4269         gc_master(stackptr);
4270   } else if(BAMBOO_NUM_OF_CORE < NUMCORES4GC) {
4271         // Zero out the remaining bamboo_cur_msp 
4272         // Only zero out the first 4 bytes of the remaining memory
4273         // Move the operation here because for the GC_CACHE_ADAPT version,
4274         // we need to make sure during the gcinit phase the shared heap is not 
4275         // touched. Otherwise, there would be problem when adapt the cache 
4276         // strategy.
4277         if((bamboo_cur_msp != 0) 
4278                 && (bamboo_smem_zero_top == bamboo_cur_msp) 
4279                 && (bamboo_smem_size > 0)) {
4280           *((int *)bamboo_cur_msp) = 0;
4281         }
4282 #ifdef GC_FLUSH_DTLB
4283         if(gc_num_flush_dtlb < GC_NUM_FLUSH_DTLB) {
4284           BAMBOO_CLEAN_DTLB();
4285           gc_num_flush_dtlb++;
4286         }
4287 #endif
4288 #ifdef GC_CACHE_ADAPT
4289 #ifdef GC_CACHE_SAMPLING
4290         if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
4291           // get the sampling data 
4292           bamboo_output_dtlb_sampling();
4293         }
4294 #endif // GC_CACHE_SAMPLING
4295 #endif // GC_CACHE_ADAPT
4296     gcprocessing = true;
4297     gc_collect(stackptr);
4298   } else {
4299         // Zero out the remaining bamboo_cur_msp 
4300         // Only zero out the first 4 bytes of the remaining memory
4301         // Move the operation here because for the GC_CACHE_ADAPT version,
4302         // we need to make sure during the gcinit phase the shared heap is not 
4303         // touched. Otherwise, there would be problem when adapt the cache 
4304         // strategy.
4305         if((bamboo_cur_msp != 0) 
4306                 && (bamboo_smem_zero_top == bamboo_cur_msp) 
4307                 && (bamboo_smem_size > 0)) {
4308           *((int *)bamboo_cur_msp) = 0;
4309         }
4310 #ifdef GC_FLUSH_DTLB
4311         if(gc_num_flush_dtlb < GC_NUM_FLUSH_DTLB) {
4312           BAMBOO_CLEAN_DTLB();
4313           gc_num_flush_dtlb++;
4314         }
4315 #endif
4316 #ifdef GC_CACHE_ADAPT
4317 #ifdef GC_CACHE_SAMPLING
4318         if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
4319           // get the sampling data 
4320           bamboo_output_dtlb_sampling();
4321         }
4322 #endif // GC_CACHE_SAMPLING
4323 #endif // GC_CACHE_ADAPT
4324     // not a gc core, should wait for gcfinish msg
4325     gcprocessing = true;
4326     gc_nocollect(stackptr);
4327   }
4328 #ifdef GC_CACHE_ADAPT
4329 #ifdef GC_CACHE_SAMPLING
4330   // enable the timer interrupt
4331   bamboo_tile_timer_set_next_event(GC_TILE_TIMER_EVENT_SETTING); 
4332   bamboo_unmask_timer_intr();
4333 #endif // GC_CACHE_SAMPLING
4334 #endif // GC_CACHE_ADAPT
4335
4336   return true;
4337 } // void gc(struct garbagelist * stackptr)
4338
4339 #ifdef GC_PROFILE
4340 inline void gc_profileStart(void) {
4341   if(!gc_infoOverflow) {
4342     GCInfo* gcInfo = RUNMALLOC(sizeof(struct gc_info));
4343     gc_infoArray[gc_infoIndex] = gcInfo;
4344     gcInfo->index = 1;
4345     gcInfo->time[0] = BAMBOO_GET_EXE_TIME();
4346   }
4347 }
4348
4349 inline void gc_profileItem(void) {
4350   if(!gc_infoOverflow) {
4351     GCInfo* gcInfo = gc_infoArray[gc_infoIndex];
4352     gcInfo->time[gcInfo->index++] = BAMBOO_GET_EXE_TIME();
4353   }
4354 }
4355
4356 inline void gc_profileEnd(void) {
4357   if(!gc_infoOverflow) {
4358     GCInfo* gcInfo = gc_infoArray[gc_infoIndex];
4359     gcInfo->time[gcInfo->index++] = BAMBOO_GET_EXE_TIME();
4360         gcInfo->time[gcInfo->index++] = gc_num_livespace;
4361         gcInfo->time[gcInfo->index++] = gc_num_freespace;
4362         gcInfo->time[gcInfo->index++] = gc_num_lobj;
4363         gcInfo->time[gcInfo->index++] = gc_num_lobjspace;
4364         gcInfo->time[gcInfo->index++] = gc_num_obj;
4365         gcInfo->time[gcInfo->index++] = gc_num_liveobj;
4366         gcInfo->time[gcInfo->index++] = gc_num_forwardobj;
4367     gc_infoIndex++;
4368     if(gc_infoIndex == GCINFOLENGTH) {
4369       gc_infoOverflow = true;
4370       //taskInfoIndex = 0;
4371     }
4372   }
4373 }
4374
4375 // output the profiling data
4376 void gc_outputProfileData() {
4377   int i = 0;
4378   int j = 0;
4379   unsigned long long totalgc = 0;
4380
4381 #ifndef BAMBOO_MEMPROF
4382   BAMBOO_PRINT(0xdddd);
4383 #endif
4384   // output task related info
4385   for(i= 0; i < gc_infoIndex; i++) {
4386     GCInfo * gcInfo = gc_infoArray[i];
4387 #ifdef BAMBOO_MEMPROF
4388     unsigned long long tmp=gcInfo->time[gcInfo->index-8]-gcInfo->time[0]; //0;
4389 #else
4390         unsigned long long tmp = 0;
4391     BAMBOO_PRINT(0xddda);
4392     for(j = 0; j < gcInfo->index - 7; j++) {
4393       BAMBOO_PRINT(gcInfo->time[j]);
4394       BAMBOO_PRINT(gcInfo->time[j]-tmp);
4395       BAMBOO_PRINT(0xdddb);
4396       tmp = gcInfo->time[j];
4397     }
4398     tmp = (tmp-gcInfo->time[0]);
4399     BAMBOO_PRINT_REG(tmp);
4400         BAMBOO_PRINT(0xdddc);
4401         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 7]);
4402         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 6]);
4403         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 5]);
4404         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 4]);
4405         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 3]);
4406         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 2]);
4407         BAMBOO_PRINT(gcInfo->time[gcInfo->index - 1]);
4408     BAMBOO_PRINT(0xddde);
4409 #endif
4410     totalgc += tmp;
4411   }
4412 #ifndef BAMBOO_MEMPROF
4413   BAMBOO_PRINT(0xdddf);
4414 #endif
4415   BAMBOO_PRINT_REG(totalgc);
4416
4417   if(gc_infoOverflow) {
4418     BAMBOO_PRINT(0xefee);
4419   }
4420
4421 #ifndef BAMBOO_MEMPROF
4422   BAMBOO_PRINT(0xeeee);
4423 #endif
4424 }
4425 #endif  // #ifdef GC_PROFILE
4426
4427 #endif