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