849916962caf91a548c164362d57ab49a6057ccb
[IRC.git] / Robust / src / Runtime / bamboo / multicoregcmark.c
1 #ifdef MULTICORE_GC
2 #include "multicoregcmark.h"
3 #include "runtime.h"
4 #include "multicoreruntime.h"
5 #include "GenericHashtable.h"
6 #include "gcqueue.h"
7
8 extern int corenum;
9 #ifdef TASK
10 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
11 extern int numqueues[][NUMCLASSES];
12 extern struct genhashtable * activetasks;
13 extern struct parameterwrapper ** objectqueues[][NUMCLASSES];
14 extern struct taskparamdescriptor *currtpd;
15 extern struct LockValue runtime_locks[MAXTASKPARAMS];
16 extern int runtime_locklen;
17 #endif
18
19 extern struct global_defs_t * global_defs_p;
20
21 #ifdef SMEMM
22 extern unsigned int gcmem_mixed_threshold;
23 extern unsigned int gcmem_mixed_usedmem;
24 #endif
25
26 #ifdef MGC
27 extern struct lockvector bamboo_threadlocks;
28 #endif
29
30 INLINE void gettype_size(void * ptr, int * ttype, unsigned int * tsize) {
31   int type = ((int *)ptr)[0];
32   unsigned int size;
33   if(type < NUMCLASSES) {
34     // a normal object
35     *tsize = classsize[type];
36     *ttype = type;
37   } else {
38     // an array
39     struct ArrayObject *ao=(struct ArrayObject *)ptr;
40     unsigned int elementsize=classsize[type];
41     unsigned int length=ao->___length___;
42     *tsize = sizeof(struct ArrayObject)+length*elementsize;
43     *ttype = type;
44   } 
45 }
46
47 INLINE bool isLarge(void * ptr, int * ttype, unsigned int * tsize) {
48   // check if a pointer is referring to a large object
49   gettype_size(ptr, ttype, tsize);
50   unsigned int bound = (BAMBOO_SMEM_SIZE);
51   if(((unsigned int)ptr-gcbaseva) < (BAMBOO_LARGE_SMEM_BOUND)) {
52     bound = (BAMBOO_SMEM_SIZE_L);
53   }
54   // ptr is a start of a block  OR it acrosses the boundary of current block
55   return (((((unsigned int)ptr-gcbaseva)%(bound))==0)||
56           ((bound-(((unsigned int)ptr-gcbaseva)%bound)) < (*tsize)));
57
58
59 INLINE unsigned int hostcore(void * ptr) {
60   // check the host core of ptr
61   unsigned int host = 0;
62   RESIDECORE(ptr, &host);
63   return host;
64
65
66 //push the null check into the mark macro
67 //#define MARKOBJ(objptr, ii) {void * marktmpptr=objptr; if (marktmpptr!=NULL) markObj(marktmpptr, __LINE__, ii);}
68
69 //#define MARKOBJNONNULL(objptr, ii) {markObj(objptr, __LINE__, ii);}
70
71 #define MARKOBJ(objptr, ii) {void * marktmpptr=objptr; if (marktmpptr!=NULL) markObj(marktmpptr);}
72
73 #define MARKOBJNONNULL(objptr, ii) {markObj(objptr);}
74
75 // NOTE: the objptr should not be NULL and should be a shared obj
76 INLINE void markObj(void * objptr) {
77   unsigned int host = hostcore(objptr);
78   if(BAMBOO_NUM_OF_CORE == host) {
79     // on this core
80     if(((struct ___Object___ *)objptr)->marked == INIT) {
81       // this is the first time that this object is discovered,
82       // set the flag as DISCOVERED
83       ((struct ___Object___ *)objptr)->marked = DISCOVERED;
84       BAMBOO_CACHE_FLUSH_LINE(objptr);
85       gc_enqueue(objptr);
86     }
87   } else {
88     // check if this obj has been forwarded
89     if(!MGCHashcontains(gcforwardobjtbl, (int)objptr)) {
90       // send a msg to host informing that objptr is active
91       send_msg_2(host,GCMARKEDOBJ,objptr);
92       GCPROFILE_RECORD_FORWARD_OBJ();
93       gcself_numsendobjs++;
94       MGCHashadd(gcforwardobjtbl, (int)objptr);
95     }
96   }
97
98
99 INLINE void markgarbagelist(struct garbagelist * listptr) {
100   for(;listptr!=NULL;listptr=listptr->next) {
101     int size=listptr->size;
102     for(int i=0; i<size; i++) {
103       MARKOBJ(listptr->array[i], i);
104     }
105   }
106 }
107
108 // enqueue root objs
109 INLINE void tomark(struct garbagelist * stackptr) {
110   BAMBOO_ASSERT(MARKPHASE == gcphase);
111
112   gcbusystatus = true;
113   gcnumlobjs = 0;
114
115   // enqueue current stack
116   markgarbagelist(stackptr);
117
118   // enqueue static pointers global_defs_p
119   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
120     markgarbagelist((struct garbagelist *)global_defs_p);
121   }
122
123 #ifdef TASK
124   // enqueue objectsets
125   if(BAMBOO_NUM_OF_CORE < NUMCORESACTIVE) {
126     for(int i=0; i<NUMCLASSES; i++) {
127       struct parameterwrapper ** queues = objectqueues[BAMBOO_NUM_OF_CORE][i];
128       int length = numqueues[BAMBOO_NUM_OF_CORE][i];
129       for(int j = 0; j < length; ++j) {
130         struct parameterwrapper * parameter = queues[j];
131         struct ObjectHash * set=parameter->objectset;
132         struct ObjectNode * ptr=set->listhead;
133         for(;ptr!=NULL;ptr=ptr->lnext) {
134           MARKOBJNONNULL((void *)ptr->key, 0);
135         }
136       }
137     }
138   }
139
140   // euqueue current task descriptor
141   if(currtpd != NULL) {
142     for(int i=0; i<currtpd->numParameters; i++) {
143       // currtpd->parameterArray[i] can not be NULL
144       MARKOBJNONNULL(currtpd->parameterArray[i], i);
145     }
146   }
147
148   // euqueue active tasks
149   if(activetasks != NULL) {
150     struct genpointerlist * ptr=activetasks->list;
151     for(;ptr!=NULL;ptr=ptr->inext) {
152       struct taskparamdescriptor *tpd=ptr->src;
153       for(int i=0; i<tpd->numParameters; i++) {
154         // the tpd->parameterArray[i] can not be NULL
155         MARKOBJNONNULL(tpd->parameterArray[i], i);
156       }
157     }
158   }
159
160   // enqueue cached transferred obj
161   struct QueueItem * tmpobjptr =  getHead(&objqueue);
162   for(;tmpobjptr != NULL;tmpobjptr=getNextQueueItem(tmpobjptr)) {
163     struct transObjInfo * objInfo=(struct transObjInfo *)(tmpobjptr->objectptr);
164     // the objptr can not be NULL
165     MARKOBJNONNULL(objInfo->objptr, 0);
166   }
167
168   // enqueue cached objs to be transferred
169   struct QueueItem * item = getHead(totransobjqueue);
170   for(;item != NULL;item=getNextQueueItem(item)) {
171     struct transObjInfo * totransobj=(struct transObjInfo *)(item->objectptr);
172     // the objptr can not be NULL
173     MARKOBJNONNULL(totransobj->objptr, 0);
174   }
175
176   // enqueue lock related info
177   for(int i = 0; i < runtime_locklen; i++) {
178     MARKOBJ((void *)(runtime_locks[i].redirectlock), 0);
179     MARKOBJ((void *)(runtime_locks[i].value), i);
180   }
181 #endif 
182
183 #ifdef MGC
184   // enqueue global thread queue
185   if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
186     lockthreadqueue();
187     unsigned int thread_counter = *((unsigned int*)(bamboo_thread_queue+1));
188     if(thread_counter > 0) {
189       unsigned int start = *((unsigned int*)(bamboo_thread_queue+2));
190       for(int i = thread_counter; i > 0; i--) {
191         // the thread obj can not be NULL
192         MARKOBJNONNULL((void *)bamboo_thread_queue[4+start], 0);
193         start = (start+1)&bamboo_max_thread_num_mask;
194       }
195     }
196   }
197
198   // enqueue the bamboo_threadlocks
199   for(int i = 0; i < bamboo_threadlocks.index; i++) {
200     // the locks can not be NULL
201     MARKOBJNONNULL((void *)(bamboo_threadlocks.locks[i].object), i);
202   }
203
204   // enqueue the bamboo_current_thread
205   MARKOBJ((void *)bamboo_current_thread, 0);
206 #endif
207 }
208
209 INLINE void scanPtrsInObj(void * ptr, int type) {
210   // scan all pointers in ptr
211   unsigned int * pointer = pointerarray[type];
212   if (pointer==0) {
213     /* Array of primitives */
214 #ifdef OBJECTHASPOINTERS
215     pointer=pointerarray[OBJECTTYPE];
216     //handle object class
217     int size=pointer[0];
218     for(int i=1; i<=size; i++) {
219       unsigned int offset=pointer[i];
220       void * objptr=*((void **)(((char *)ptr)+offset));
221       MARKOBJ(objptr, i);
222     }
223 #endif
224   } else if (((unsigned int)pointer)==1) {
225     /* Array of pointers */
226     struct ArrayObject *ao=(struct ArrayObject *) ptr;
227     int length=ao->___length___;
228     for(int i=0; i<length; i++) {
229       void *objptr=((void **)(((char *)&ao->___length___)+sizeof(int)))[i];
230       MARKOBJ(objptr, i);
231     }
232 #ifdef OBJECTHASPOINTERS
233     pointer=pointerarray[OBJECTTYPE];
234     //handle object class
235     int size=pointer[0];
236     for(int i=1; i<=size; i++) {
237       unsigned int offset=pointer[i];
238       void * objptr=*((void **)(((char *)ptr)+offset));
239       MARKOBJ(objptr, i);
240     }
241 #endif
242   } else {
243     /* Normal Object */
244     int size=pointer[0];
245     for(int i=1; i<=size; i++) {
246       unsigned int offset=pointer[i];
247       void * objptr=*((void **)(((char *)ptr)+offset));
248       MARKOBJ(objptr, i);
249     }
250   }
251 }
252
253 INLINE void mark(bool isfirst, struct garbagelist * stackptr) {
254   if(isfirst) {
255     // enqueue root objs
256     tomark(stackptr);
257     gccurr_heaptop = 0; // record the size of all active objs in this core
258                         // aligned but does not consider block boundaries
259     gcmarkedptrbound = 0;
260   }
261   unsigned int isize = 0;
262   bool sendStall = false;
263   // mark phase
264   while(MARKPHASE == gcphase) {
265     int counter = 0;
266     while(gc_moreItems2()) {
267       sendStall = false;
268       gcbusystatus = true;
269       unsigned int ptr = gc_dequeue2();
270
271       unsigned int size = 0;
272       unsigned int isize = 0;
273       unsigned int type = 0;
274       // check if it is a local obj on this core
275       if(((struct ___Object___ *)ptr)->marked!=DISCOVERED) {
276         // ptr has been marked
277         continue;
278       } else if(isLarge(ptr, &type, &size)) {
279         // ptr is a large object and not marked or enqueued
280         gc_lobjenqueue(ptr, size, BAMBOO_NUM_OF_CORE);
281         gcnumlobjs++;
282       } else {
283         // ptr is an unmarked active object on this core
284         ALIGNSIZE(size, &isize);
285         gccurr_heaptop += isize;
286         
287         if((unsigned int)(ptr + size) > (unsigned int)gcmarkedptrbound) {
288           gcmarkedptrbound = (unsigned int)(ptr + size);
289         }
290       }
291       // mark this obj
292       ((struct ___Object___ *)ptr)->marked = MARKED;
293       BAMBOO_CACHE_FLUSH_LINE(ptr);
294       // scan the pointers in object
295       scanPtrsInObj(ptr, type);      
296     }   
297     gcbusystatus = false;
298     // send mark finish msg to core coordinator
299     if(STARTUPCORE == BAMBOO_NUM_OF_CORE) {
300       int entry_index = waitconfirm ? (gcnumsrobjs_index==0) : gcnumsrobjs_index;
301       gccorestatus[BAMBOO_NUM_OF_CORE] = 0;
302       gcnumsendobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numsendobjs;
303       gcnumreceiveobjs[entry_index][BAMBOO_NUM_OF_CORE]=gcself_numreceiveobjs;
304       gcloads[BAMBOO_NUM_OF_CORE] = gccurr_heaptop;
305     } else {
306       if(!sendStall) {
307         send_msg_4(STARTUPCORE,GCFINISHMARK,BAMBOO_NUM_OF_CORE,gcself_numsendobjs,gcself_numreceiveobjs);
308         sendStall = true;
309       }
310     }
311     
312     if(BAMBOO_NUM_OF_CORE == STARTUPCORE)
313       return;
314   }
315
316   BAMBOO_CACHE_MF();
317
318
319 #endif // MULTICORE_GC