Some code clean and make the cache adapt version compile
[IRC.git] / Robust / src / Runtime / bamboo / multicoregccompact.c
1 #ifdef MULTICORE_GC
2 #include "multicoregccompact.h"
3 #include "runtime_arch.h"
4 #include "multicoreruntime.h"
5 #include "multicoregarbage.h"
6
7 INLINE bool gc_checkCoreStatus() {
8   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
9   for(int i = 0; i < NUMCORES4GC; ++i) {
10     if(gccorestatus[i] != 0) {
11       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
12       return false;
13     }
14   }  
15   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
16   return true;
17 }
18
19 INLINE void gc_resetCoreStatus() {
20   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
21   for(int i = 0; i < NUMCORES4GC; ++i) {
22     gccorestatus[i] = 1;
23   }
24   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
25 }
26
27 // should be invoked with interrupt closed
28 INLINE int assignSpareMem_I(unsigned int sourcecore,unsigned int * requiredmem,unsigned int * tomove,unsigned int * startaddr) {
29   unsigned int b = 0;
30   BLOCKINDEX(gcloads[sourcecore], &b);
31   unsigned int boundptr = BOUNDPTR(b);
32   unsigned int remain = boundptr - gcloads[sourcecore];
33   unsigned int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
34   *startaddr = gcloads[sourcecore];
35   *tomove = gcfilledblocks[sourcecore] + 1;
36   if(memneed < remain) {
37     gcloads[sourcecore] += memneed;
38     return 0;
39   } else {
40     // next available block
41     gcfilledblocks[sourcecore] += 1;
42     unsigned int newbase = 0;
43     BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
44     gcloads[sourcecore] = newbase;
45     return requiredmem-remain;
46   }
47 }
48
49 INLINE int assignSpareMem(unsigned int sourcecore,unsigned int * requiredmem,unsigned int * tomove,unsigned int * startaddr) {
50   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
51   unsigned int b = 0;
52   BLOCKINDEX(gcloads[sourcecore], &b);
53   unsigned int boundptr = BOUNDPTR(b);
54   unsigned int remain = boundptr - gcloads[sourcecore];
55   unsigned int memneed = requiredmem + BAMBOO_CACHE_LINE_SIZE;
56   *startaddr = gcloads[sourcecore];
57   *tomove = gcfilledblocks[sourcecore] + 1;
58   if(memneed < remain) {
59     gcloads[sourcecore] += memneed;
60     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
61     return 0;
62   } else {
63     // next available block
64     gcfilledblocks[sourcecore] += 1;
65     unsigned int newbase = 0;
66     BASEPTR(sourcecore, gcfilledblocks[sourcecore], &newbase);
67     gcloads[sourcecore] = newbase;
68     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
69     return requiredmem-remain;
70   }
71 }
72
73 INLINE void compact2Heaptophelper_I(unsigned int coren,unsigned int* p,unsigned int* numblocks,unsigned int* remain) {
74   unsigned int b;
75   unsigned int memneed = gcrequiredmems[coren] + BAMBOO_CACHE_LINE_SIZE;
76   if(STARTUPCORE == coren) {
77     gctomove = true;
78     gcmovestartaddr = *p;
79     gcdstcore = gctopcore;
80     gcblock2fill = *numblocks + 1;
81   } else {
82     if(BAMBOO_CHECK_SEND_MODE()) {
83       cache_msg_4_I(coren,GCMOVESTART,gctopcore,*p,(*numblocks)+1);
84     } else {
85       send_msg_4_I(coren,GCMOVESTART,gctopcore,*p,(*numblocks)+1);
86     }
87   }
88   if(memneed < *remain) {
89     *p = *p + memneed;
90     gcrequiredmems[coren] = 0;
91     gcloads[gctopcore] += memneed;
92     *remain = *remain - memneed;
93   } else {
94     // next available block
95     *p = *p + *remain;
96     gcfilledblocks[gctopcore] += 1;
97     unsigned int newbase = 0;
98     BASEPTR(gctopcore, gcfilledblocks[gctopcore], &newbase);
99     gcloads[gctopcore] = newbase;
100     gcrequiredmems[coren] -= *remain - BAMBOO_CACHE_LINE_SIZE;
101     gcstopblock[gctopcore]++;
102     gctopcore = NEXTTOPCORE(gctopblock);
103     gctopblock++;
104     *numblocks = gcstopblock[gctopcore];
105     *p = gcloads[gctopcore];
106     BLOCKINDEX(*p, &b);
107     *remain=GC_BLOCK_REMAIN_SIZE(b, (*p));
108   }  
109   gcmovepending--;
110
111
112 INLINE void compact2Heaptop() {
113   // no cores with spare mem and some cores are blocked with pending move
114   // find the current heap top and make them move to the heap top
115   unsigned int p;
116   unsigned int numblocks = gcfilledblocks[gctopcore];
117   p = gcloads[gctopcore];
118   unsigned int b;
119   BLOCKINDEX(p, &b);
120   unsigned int remain=GC_BLOCK_REMAIN_SIZE(b, p);
121   // check if the top core finishes
122   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
123   if(gccorestatus[gctopcore] != 0) {
124     // let the top core finishes its own work first
125     compact2Heaptophelper_I(gctopcore, &p, &numblocks, &remain);
126     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
127     return;
128   }
129   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
130
131   for(int i = 0; i < NUMCORES4GC; i++) {
132     BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
133     if((gccorestatus[i] != 0) && (gcrequiredmems[i] > 0)) {
134       compact2Heaptophelper_I(i, &p, &numblocks, &remain);
135       if(gccorestatus[gctopcore] != 0) {
136         BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
137         // the top core is not free now
138         return;
139       }
140     }  
141     BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
142   } 
143 }
144
145 INLINE void resolvePendingMoveRequest() {
146   int i;
147   int j;
148   bool nosparemem = true;
149   bool haspending = false;
150   bool hasrunning = false;
151   bool noblock = false;
152   unsigned int dstcore = 0;       // the core who need spare mem
153   unsigned int sourcecore = 0;       // the core who has spare mem
154   for(i = j = 0; (i < NUMCORES4GC) && (j < NUMCORES4GC); ) {
155     if(nosparemem) {
156       // check if there are cores with spare mem
157       if(gccorestatus[i] == 0) {
158         // finished working, check if it still have spare mem
159         if(gcfilledblocks[i] < gcstopblock[i]) {
160           // still have spare mem
161           nosparemem = false;
162           sourcecore = i;
163         }  
164       }
165       i++;
166     }  
167     if(!haspending) {
168       if(gccorestatus[j] != 0) {
169         // not finished, check if it has pending move requests
170         if((gcfilledblocks[j]==gcstopblock[j])&&(gcrequiredmems[j]>0)) {
171           dstcore = j;
172           haspending = true;
173         } else {
174           hasrunning = true;
175         } 
176       } 
177       j++;
178     }  
179     if(!nosparemem && haspending) {
180       // find match
181       unsigned int tomove = 0;
182       unsigned int startaddr = 0;
183       gcrequiredmems[dstcore] = assignSpareMem(sourcecore,gcrequiredmems[dstcore],&tomove,&startaddr);
184       if(STARTUPCORE == dstcore) {
185         gcdstcore = sourcecore;
186         gctomove = true;
187         gcmovestartaddr = startaddr;
188         gcblock2fill = tomove;
189       } else {
190         send_msg_4(dstcore,GCMOVESTART,sourcecore,startaddr,tomove);
191       }
192       gcmovepending--;
193       nosparemem = true;
194       haspending = false;
195       noblock = true;
196     }
197   }  
198   
199   if(!hasrunning && !noblock) {
200     gc_status_info.gcphase = SUBTLECOMPACTPHASE;
201     compact2Heaptop();
202   }
203
204
205 // If out of boundary of valid shared memory, return false, else return true
206 INLINE bool nextSBlock(struct moveHelper * orig) {
207   orig->blockbase = orig->blockbound;
208   
209   bool sbchanged = false;
210   unsigned int origptr = orig->ptr;
211   unsigned int blockbase = orig->blockbase;
212   unsigned int blockbound = orig->blockbound;
213   unsigned int bound = orig->bound;
214 outernextSBlock:
215   // check if across a big block
216   // TODO now do not zero out the whole memory, maybe the last two conditions
217   // are useless now
218   if((blockbase>=bound)||(origptr>=bound)||((origptr!=NULL)&&(*((int*)origptr))==0)||((*((int*)blockbase))==0)) {
219   innernextSBlock:
220     // end of current heap block, jump to next one
221     orig->numblocks++;
222     BASEPTR(BAMBOO_NUM_OF_CORE, orig->numblocks, &(orig->base));
223     if(orig->base >= gcbaseva + BAMBOO_SHARED_MEM_SIZE) {
224       // out of boundary
225       orig->ptr = orig->base; // set current ptr to out of boundary too
226       return false;
227     }
228     orig->blockbase = orig->base;
229     orig->sblockindex=(unsigned int)(orig->blockbase-gcbaseva)/BAMBOO_SMEM_SIZE;
230     sbchanged = true;
231     unsigned int blocknum = 0;
232     BLOCKINDEX(orig->base, &blocknum);
233     if(bamboo_smemtbl[blocknum] == 0) {
234       // goto next block
235       goto innernextSBlock;
236     }
237     // check the bamboo_smemtbl to decide the real bound
238     orig->bound = orig->base + bamboo_smemtbl[blocknum];
239   } else if(0 == (orig->blockbase%BAMBOO_SMEM_SIZE)) {
240     orig->sblockindex += 1;
241     sbchanged = true;
242   }  
243
244   // check if this sblock should be skipped or have special start point
245   int sbstart = gcsbstarttbl[orig->sblockindex];
246   if(sbstart == -1) {
247     // goto next sblock
248     orig->sblockindex += 1;
249     orig->blockbase += BAMBOO_SMEM_SIZE;
250     goto outernextSBlock;
251   } else if((sbstart != 0) && (sbchanged)) {
252     // the first time to access this SBlock
253     // not start from the very beginning
254     orig->blockbase = sbstart;
255   } 
256
257   // setup information for this sblock
258   orig->blockbound = orig->blockbase+(unsigned int)*((int*)(orig->blockbase));
259   orig->offset = BAMBOO_CACHE_LINE_SIZE;
260   orig->ptr = orig->blockbase + orig->offset;
261   if(orig->ptr >= orig->bound) {
262     // met a lobj, move to next block
263     goto innernextSBlock;
264   }
265
266   return true;
267
268
269 // return false if there are no available data to compact
270 INLINE bool initOrig_Dst(struct moveHelper * orig,struct moveHelper * to) {
271   // init the dst ptr
272   to->numblocks = 0;
273   to->top = to->offset = BAMBOO_CACHE_LINE_SIZE;
274   to->bound = BAMBOO_SMEM_SIZE_L;
275   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
276
277   unsigned int tobase = to->base;
278   to->ptr = tobase + to->offset;
279
280   // init the orig ptr
281   orig->numblocks = 0;
282   orig->base = tobase;
283   unsigned int blocknum = 0;
284   BLOCKINDEX(orig->base, &blocknum);
285   unsigned int origbase = orig->base;
286   // check the bamboo_smemtbl to decide the real bound
287   orig->bound = origbase + (unsigned int)bamboo_smemtbl[blocknum];
288   orig->blockbase = origbase;
289   orig->sblockindex = (unsigned int)(origbase - gcbaseva) / BAMBOO_SMEM_SIZE;
290
291   int sbstart = gcsbstarttbl[orig->sblockindex];
292   if(sbstart == -1) {
293     // goto next sblock
294     orig->blockbound=gcbaseva+BAMBOO_SMEM_SIZE*(orig->sblockindex+1);
295     return nextSBlock(orig);
296   } else if(sbstart != 0) {
297     orig->blockbase = sbstart;
298   }
299   orig->blockbound = orig->blockbase + *((int*)(orig->blockbase));
300   orig->offset = BAMBOO_CACHE_LINE_SIZE;
301   orig->ptr = orig->blockbase + orig->offset;
302
303   return true;
304 }
305
306 INLINE void nextBlock(struct moveHelper * to) {
307   to->top = to->bound + BAMBOO_CACHE_LINE_SIZE; // header!
308   to->bound += BAMBOO_SMEM_SIZE;
309   to->numblocks++;
310   BASEPTR(BAMBOO_NUM_OF_CORE, to->numblocks, &(to->base));
311   to->offset = BAMBOO_CACHE_LINE_SIZE;
312   to->ptr = to->base + to->offset;
313 }
314
315 INLINE unsigned int findValidObj(struct moveHelper * orig,struct moveHelper * to,int * type) {
316   unsigned int size = 0;
317   while(true) {
318     CACHEADAPT_COMPLETE_PAGE_CONVERT(orig, to, to->ptr, false);
319     unsigned int origptr = (unsigned int)(orig->ptr);
320     unsigned int origbound = (unsigned int)orig->bound;
321     unsigned int origblockbound = (unsigned int)orig->blockbound;
322     if((origptr >= origbound) || (origptr == origblockbound)) {
323       if(!nextSBlock(orig)) {
324         // finished, no more data
325         return -1;
326       }
327       continue;
328     }
329     // check the obj's type, size and mark flag
330     *type = ((int *)(origptr))[0];
331     size = 0;
332     if(*type == 0) {
333       // end of this block, go to next one
334       if(!nextSBlock(orig)) {
335         // finished, no more data
336         return -1;
337       }
338       continue;
339     } else if(*type < NUMCLASSES) {
340       // a normal object
341       size = classsize[*type];
342     } else {
343       // an array
344       struct ArrayObject *ao=(struct ArrayObject *)(origptr);
345       unsigned int elementsize=classsize[*type];
346       unsigned int length=ao->___length___;
347       size=(unsigned int)sizeof(struct ArrayObject)
348         +(unsigned int)(length*elementsize);
349     }
350     return size;
351   }
352 }
353
354 // endaddr does not contain spaces for headers
355 INLINE bool moveobj(struct moveHelper * orig, struct moveHelper * to, unsigned int stopblock) {
356   if(stopblock == 0) {
357     return true;
358   }
359
360   int type = 0;
361   unsigned int size = findValidObj(orig, to, &type);
362   unsigned int isize = 0;
363
364   if(size == -1) {
365     // finished, no more data
366     return true;
367   }
368   ALIGNSIZE(size, &isize);       // no matter is the obj marked or not
369                                  // should be able to across
370   unsigned int origptr = (unsigned int)(orig->ptr);
371   if(((struct ___Object___ *)origptr)->marked == MARKED) {
372     unsigned int totop = (unsigned int)to->top;
373     unsigned int tobound = (unsigned int)to->bound;
374     GCPROFILE_RECORD_LIVE_OBJ();
375     // marked obj, copy it to current heap top
376     // check to see if remaining space is enough
377     if((unsigned int)(totop + isize) > tobound) {
378       // fill 0 indicating the end of this block
379       BAMBOO_MEMSET_WH(to->ptr,  '\0', tobound - totop);
380       // fill the header of this block and then go to next block
381       to->offset += tobound - totop;
382       CLOSEBLOCK(to->base, to->offset);
383 #ifdef GC_CACHE_ADAPT
384       unsigned int tmp_ptr = to->ptr;
385 #endif 
386       nextBlock(to);
387 #ifdef GC_CACHE_ADAPT
388       CACHEADAPT_COMPLETE_PAGE_CONVERT(orig, to, tmp_ptr, true);
389 #endif 
390       if(stopblock == to->numblocks) {
391         // already fulfilled the block
392         return true;
393       }  
394     } 
395     // set the mark field to 2, indicating that this obj has been moved
396     // and need to be flushed
397     ((struct ___Object___ *)origptr)->marked = COMPACTED;
398     unsigned int toptr = (unsigned int)to->ptr;
399     if(toptr != origptr) {
400       if((unsigned int)(origptr) < (unsigned int)(toptr+size)) {
401         memmove(toptr, origptr, size);
402       } else {
403         memcpy(toptr, origptr, size);
404       }
405       // fill the remaining space with -2
406       BAMBOO_MEMSET_WH((unsigned int)(toptr+size), -2, isize-size);
407     }
408     // store mapping info
409     gcmappingtbl[OBJMAPPINGINDEX((unsigned int)origptr)]=(unsigned int)toptr;
410     gccurr_heaptop -= isize;
411     to->ptr += isize;
412     to->offset += isize;
413     to->top += isize;
414 #ifdef GC_CACHE_ADAPT
415     unsigned int tmp_ptr = to->ptr;
416 #endif // GC_CACHE_ADAPT
417     if(to->top == to->bound) {
418       CLOSEBLOCK(to->base, to->offset);
419       nextBlock(to);
420     }
421 #ifdef GC_CACHE_ADAPT
422     CACHEADAPT_COMPLETE_PAGE_CONVERT(orig, to, tmp_ptr, true);
423 #endif
424   } 
425   
426   // move to next obj
427   orig->ptr += isize; 
428   
429   return ((((unsigned int)(orig->ptr) > (unsigned int)(orig->bound))||((unsigned int)(orig->ptr) == (unsigned int)(orig->blockbound)))&&!nextSBlock(orig));
430
431
432 // should be invoked with interrupt closed
433 bool gcfindSpareMem_I(unsigned int * startaddr,unsigned int * tomove,unsigned int * dstcore,unsigned int requiredmem,unsigned int requiredcore) {
434   for(int k = 0; k < NUMCORES4GC; k++) {
435     if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
436       // check if this stopped core has enough mem
437       assignSpareMem_I(k, requiredmem, tomove, startaddr);
438       *dstcore = k;
439       return true;
440     }
441   }
442   // if can not find spare mem right now, hold the request
443   gcrequiredmems[requiredcore] = requiredmem;
444   gcmovepending++;
445   return false;
446
447
448 bool gcfindSpareMem(unsigned int * startaddr,unsigned int * tomove,unsigned int * dstcore,unsigned int requiredmem,unsigned int requiredcore) {
449   BAMBOO_ENTER_RUNTIME_MODE_FROM_CLIENT();
450   for(int k = 0; k < NUMCORES4GC; k++) {
451     if((gccorestatus[k] == 0) && (gcfilledblocks[k] < gcstopblock[k])) {
452       // check if this stopped core has enough mem
453       assignSpareMem_I(k, requiredmem, tomove, startaddr);
454       *dstcore = k;
455       BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
456       return true;
457     }
458   }
459   // if can not find spare mem right now, hold the request
460   gcrequiredmems[requiredcore] = requiredmem;
461   gcmovepending++;
462   BAMBOO_ENTER_CLIENT_MODE_FROM_RUNTIME();
463   return false;
464 }
465
466 INLINE bool compacthelper(struct moveHelper * orig,struct moveHelper * to,int * filledblocks,unsigned int * heaptopptr,bool * localcompact) {
467   // scan over all objs in this block, compact the marked objs
468   // loop stop when finishing either scanning all active objs or
469   // fulfilled the gcstopblock
470 innercompact:
471   while((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
472     if(moveobj(orig, to, gcblock2fill)) {
473       break;
474     }
475   }
476   CACHEADAPT_SAMPLING_DATA_CONVERT(to->ptr);
477   // if no objs have been compact, do nothing,
478   // otherwise, fill the header of this block
479   if(to->offset > (unsigned int)BAMBOO_CACHE_LINE_SIZE) {
480     CLOSEBLOCK(to->base, to->offset);
481   } else {
482     to->offset = 0;
483     to->ptr = to->base;
484     to->top -= BAMBOO_CACHE_LINE_SIZE;
485   }  
486   if(*localcompact) {
487     *heaptopptr = to->ptr;
488     *filledblocks = to->numblocks;
489   }
490   
491   // send msgs to core coordinator indicating that the compact is finishing
492   // send compact finish message to core coordinator
493   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
494     gcfilledblocks[BAMBOO_NUM_OF_CORE] = *filledblocks;
495     gcloads[BAMBOO_NUM_OF_CORE] = *heaptopptr;
496     if((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
497       // ask for more mem
498       gctomove = false;
499       if(gcfindSpareMem(&gcmovestartaddr,&gcblock2fill,&gcdstcore,gccurr_heaptop,BAMBOO_NUM_OF_CORE)) {
500         gctomove = true;
501       } else {
502         return false;
503       }
504     } else {
505       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
506       gctomove = false;
507       return true;
508     }
509   } else {
510     if((unsigned int)(orig->ptr) < (unsigned int)gcmarkedptrbound) {
511       // ask for more mem
512       gctomove = false;
513       send_msg_5(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE,*filledblocks,*heaptopptr,gccurr_heaptop);
514     } else {
515       // finish compacting
516       send_msg_5(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE,*filledblocks,*heaptopptr, 0);
517     }
518   } 
519
520   if(orig->ptr < gcmarkedptrbound) {
521     // still have unpacked obj
522     while(!gctomove) ;
523     
524     gctomove = false;
525
526     to->ptr = gcmovestartaddr;
527     to->numblocks = gcblock2fill - 1;
528     to->bound = BLOCKBOUND(to->numblocks);
529     BASEPTR(gcdstcore, to->numblocks, &(to->base));
530     to->offset = to->ptr - to->base;
531     to->top=(to->numblocks==0)?(to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
532     to->base = to->ptr;
533     to->offset = BAMBOO_CACHE_LINE_SIZE;
534     to->ptr += to->offset;   // for header
535     to->top += to->offset;
536     *localcompact = (gcdstcore == BAMBOO_NUM_OF_CORE);
537     CACHEADAPT_SAMPLING_DATA_REVISE_INIT(orig, to);
538     goto innercompact;
539   }
540   return true;
541 }
542
543 void compact() {
544   BAMBOO_ASSERT(COMPACTPHASE == gc_status_info.gcphase);
545   
546   // initialize pointers for comapcting
547   struct moveHelper * orig = (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
548   struct moveHelper * to = (struct moveHelper *)RUNMALLOC(sizeof(struct moveHelper));
549   if(!initOrig_Dst(orig, to)) {
550     // no available data to compact
551     // send compact finish msg to STARTUP core
552     send_msg_5(STARTUPCORE,GCFINISHCOMPACT,BAMBOO_NUM_OF_CORE,0,to->base,0);
553     RUNFREE(orig);
554     RUNFREE(to);
555   } else {
556     CACHEADAPT_SAMPLING_DATA_REVISE_INIT(orig, to);
557
558     unsigned int filledblocks = 0;
559     unsigned int heaptopptr = 0;
560     bool localcompact = true;
561     compacthelper(orig, to, &filledblocks, &heaptopptr, &localcompact);
562     RUNFREE(orig);
563     RUNFREE(to);
564   }
565
566
567 void compact_master(struct moveHelper * orig, struct moveHelper * to) {
568   // initialize pointers for comapcting
569   initOrig_Dst(orig, to);
570   CACHEADAPT_SAMPLING_DATA_REVISE_INIT(orig, to);
571   int filledblocks = 0;
572   unsigned int heaptopptr = 0;
573   bool finishcompact = false;
574   bool iscontinue = true;
575   bool localcompact = true;
576   while((COMPACTPHASE == gc_status_info.gcphase) || (SUBTLECOMPACTPHASE == gc_status_info.gcphase)) {
577     if((!finishcompact) && iscontinue) {
578       finishcompact = compacthelper(orig,to,&filledblocks,&heaptopptr,&localcompact);
579     }
580     
581     if(gc_checkCoreStatus()) {
582       // all cores have finished compacting restore the gcstatus of all cores
583       gc_resetCoreStatus();
584       break;
585     } else {
586       // check if there are spare mem for pending move requires
587       if(COMPACTPHASE == gc_status_info.gcphase) {
588         resolvePendingMoveRequest();
589       } else {
590         compact2Heaptop();
591       }
592     } 
593
594     if(gctomove) {
595       to->ptr = gcmovestartaddr;
596       to->numblocks = gcblock2fill - 1;
597       to->bound = BLOCKBOUND(to->numblocks);
598       BASEPTR(gcdstcore, to->numblocks, &(to->base));
599       to->offset = to->ptr - to->base;
600       to->top = (to->numblocks==0)?(to->offset):(to->bound-BAMBOO_SMEM_SIZE+to->offset);
601       to->base = to->ptr;
602       to->offset = BAMBOO_CACHE_LINE_SIZE;
603       to->ptr += to->offset;  // for header
604       to->top += to->offset;
605       localcompact = (gcdstcore == BAMBOO_NUM_OF_CORE);
606       gctomove = false;
607       iscontinue = true;
608     } else if(!finishcompact) {
609       // still pending
610       iscontinue = false;
611     }
612   }
613 }
614
615 #endif // MULTICORE_GC