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