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