Add cache adaptive code to multicore gc and add support for System.gc()
[IRC.git] / Robust / src / Runtime / bamboo / multicorecache.h
1 #ifndef BAMBOO_MULTICORE_CACHE_H
2 #define BAMBOO_MULTICORE_CACHE_H
3 #ifdef MULTICORE_GC
4 #include "multicore.h"
5 #include "multicoremem.h"
6 #include "multicoregccompact.h"
7 #include "multicoregarbage.h"
8
9 #ifdef GC_CACHE_ADAPT
10 // sampling unit to compute access frequency, this should be consistent all the
11 // time.
12 #define GC_CACHE_SAMPLING_UNIT 0x80000 
13 // freqeuency to trigger timer interrupt
14 #define GC_TILE_TIMER_EVENT_SETTING 10000000  
15
16 // data structure to record policy information for a page
17 // should be consistent with multicoreruntime.h
18 typedef union
19 {
20   unsigned int word;
21   struct
22   {
23     // policy type, should be enough to accommodate all 4 possible polices
24     unsigned int cache_mode   : 3;
25     // Reserved.
26     unsigned int __reserved_0 : 5;
27     // Location Override Target Y
28     unsigned int lotar_y      : 4;
29     // Reserved.
30     unsigned int __reserved_1 : 4;
31     // Location Override Target X
32     unsigned int lotar_x      : 4;
33     // Reserved.
34     unsigned int __reserved_2 : 12;
35   };
36 } bamboo_cache_policy_t;
37
38 #define BAMBOO_CACHE_MODE_LOCAL 1  // locally cached
39 #define BAMBOO_CACHE_MODE_HASH 2   // hash-for-home
40 #define BAMBOO_CACHE_MODE_NONE 3   // no caching
41 #define BAMBOO_CACHE_MODE_COORDS 4 // cached on a specific core
42
43 // data structure to hold page information while calculating revised sampling 
44 // info during compaction
45 typedef struct gc_cache_revise_info {
46   // the start address in current original page to be compacted to current 
47   // destination page
48   void * orig_page_start_va; 
49   // the end of current original page to be compacted
50   void * orig_page_end_va;
51   // the index of current original page
52   unsigned int orig_page_index;
53   // the start address in current destination page to where the current original
54   // page is compacted
55   void * to_page_start_va;
56   // the end of current destination page
57   void * to_page_end_va;
58   // the index of current destination page
59   unsigned int to_page_index;
60 } gc_cache_revise_info_t;
61
62 // global variable holding page information to compute revised sampling info
63 extern gc_cache_revise_info_t gc_cache_revise_information;
64
65 /* This function initialize the gc_cache_revise_information. It should be 
66  * invoked before we start compaction.
67  */
68 INLINE static void samplingDataReviseInit(struct moveHelper * orig,struct moveHelper * to) {
69   // initialize the destination page info
70   gc_cache_revise_information.to_page_start_va=to->ptr;
71   unsigned int toindex=(unsigned INTPTR)(to->base-gcbaseva)/BAMBOO_PAGE_SIZE;
72   gc_cache_revise_information.to_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(toindex+1);
73   gc_cache_revise_information.to_page_index=toindex;
74   // initilaize the original page info
75   unsigned int origindex=((unsigned INTPTR)(orig->base-gcbaseva))/BAMBOO_PAGE_SIZE;
76   gc_cache_revise_information.orig_page_start_va=orig->ptr;
77   gc_cache_revise_information.orig_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(origindex+1);
78   gc_cache_revise_information.orig_page_index=origindex;
79 }
80
81 /* This function computes the revised profiling data of the first closed destination 
82  * page of an object that acrosses multiple pages
83  */
84 INLINE static void firstPageConvert(bool origclosefirst, unsigned INTPTR main_factor, unsigned INTPTR delta_factor) {
85   unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
86   unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
87   int * newtable=&gccachesamplingtbl_r[topage];
88   int * oldtable=&gccachesamplingtbl[oldpage];
89   // compute the revised profiling info for the start destination page
90   if(origclosefirst) {
91     // the start original page closes first, now compute the revised profiling
92     // info for the start destination page.
93     // The start destination page = the rest of the start original page + 
94     //                              delta_fator from the next original page
95     int * oldtable_next=&gccachesamplingtbl[oldpage+1];
96     for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
97       (*newtable)=((*newtable)+(*oldtable)*main_factor+(*oldtable_next)*delta_factor);
98       newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
99       oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
100       oldtable_next=(int*) (((char *)oldtable_next)+size_cachesamplingtbl_local);
101     }
102     // close the start original page 
103     gc_cache_revise_information.orig_page_start_va+=main_factor+delta_factor;
104     gc_cache_revise_information.orig_page_end_va+=BAMBOO_PAGE_SIZE;
105     gc_cache_revise_information.orig_page_index++;
106   } else {
107     // the start destination page closes first, now compute the revised 
108     // profiling info for it.
109     for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
110       (*newtable)=((*newtable)+(*oldtable)*main_factor);
111       newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
112       oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
113     }
114     // record the new start of the original page
115     gc_cache_revise_information.orig_page_start_va+=main_factor;
116   }
117   // close the start original page and destination page
118   gc_cache_revise_information.to_page_start_va=gc_cache_revise_information.to_page_end_va;
119   gc_cache_revise_information.to_page_end_va+=BAMBOO_PAGE_SIZE;
120   gc_cache_revise_information.to_page_index++;
121 }
122
123 /* This function computes the revised profiling info for closed destination 
124  * pages that are occupied by one object that acrosses multiple pages.
125  * the destination page = main_factor from the first unclosed original page 
126  *                       + delta_factor from the next unclosed original page
127  */
128 INLINE static void restClosedPageConvert(void * current_ptr, unsigned INTPTR main_factor, unsigned INTPTR delta_factor) {
129   while(gc_cache_revise_information.to_page_end_va<=current_ptr) {
130     unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
131     unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
132     int *newtable=&gccachesamplingtbl_r[topage];
133     int *oldtable=&gccachesamplingtbl[oldpage];
134     int *oldtable_next=&gccachesamplingtbl[oldpage+1];
135
136     for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
137       (*newtable)=((*newtable)+(*oldtable)*main_factor+(*oldtable_next)*delta_factor);
138       newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
139       oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
140       oldtable_next=(int*) (((char *)oldtable_next)+size_cachesamplingtbl_local);
141     }
142
143     // close the original page and the destination page
144     gc_cache_revise_information.orig_page_start_va+=BAMBOO_PAGE_SIZE;
145     gc_cache_revise_information.orig_page_end_va+=BAMBOO_PAGE_SIZE;
146     gc_cache_revise_information.orig_page_index++;
147     gc_cache_revise_information.to_page_start_va=gc_cache_revise_information.to_page_end_va;
148     gc_cache_revise_information.to_page_end_va+=BAMBOO_PAGE_SIZE;
149     gc_cache_revise_information.to_page_index++;
150   }
151 }
152
153 /* This function computes the revised profiling info for the last
154  * destination page of an object that acrosses multiple pages.
155  */
156 INLINE static void lastPageConvert(void * current_ptr) {
157   unsigned INTPTR to_factor=current_ptr-gc_cache_revise_information.to_page_start_va;
158   unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
159   unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
160   int *newtable=&gccachesamplingtbl_r[topage];
161   int *oldtable=&gccachesamplingtbl[oldpage];
162
163   for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
164     (*newtable)=((*newtable)+(*oldtable)*to_factor);
165     newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
166     oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
167   }
168   // do not need to set gc_cache_revise_information here for the last 
169   // original/destination page as it will be set in completePageConvert()
170 }
171
172 /* This function converts multiple original pages profiling data to multiple 
173  * destination pages' profiling data
174  */
175 INLINE static void samplingDataConvertMultiple(void * current_ptr) {
176   // first decide which page close first: original or destination?
177   unsigned INTPTR to_factor=(unsigned INTPTR)(gc_cache_revise_information.to_page_end_va-gc_cache_revise_information.to_page_start_va);
178   unsigned INTPTR orig_factor=(unsigned INTPTR)(gc_cache_revise_information.orig_page_end_va-gc_cache_revise_information.orig_page_start_va);
179   bool origclosefirst=to_factor>orig_factor;
180   unsigned INTPTR delta_factor=(origclosefirst)?(to_factor-orig_factor):(orig_factor-to_factor);
181   unsigned INTPTR main_factor=(origclosefirst)?orig_factor:to_factor;
182
183   // compute the revised profiling info for the start destination page
184   firstPageConvert(origclosefirst, main_factor, delta_factor);
185   // update main_factor/delta_factor
186   if(origclosefirst) {
187     // for the following destination pages that are fully used:
188     // the destination page = (page_size-delta_factor) from the 
189     //                        first unclosed original page + delta_factor 
190     //                        from the next unclosed original page
191     // we always use main_factor to represent the factor from the first 
192     // unclosed original page
193     main_factor=BAMBOO_PAGE_SIZE-delta_factor;
194   } else {
195     // for the following destination pages that are fully used:
196     // the destination page = delta_factor from the first unclosed original    
197     //                        page + (page_size-delta_factor) from the next 
198     //                        unclosed original page
199     // we always use main_factor to represent the factor from the first
200     // unclosed original page
201     main_factor=delta_factor;
202     delta_factor=BAMBOO_PAGE_SIZE-delta_factor;
203   }
204
205   // compute the revised profiling info for the following closed destination
206   // pages
207   restClosedPageConvert(current_ptr, main_factor, delta_factor);
208
209   // compute the revised profiling info for the last destination page if needed
210   lastPageConvert(current_ptr);
211 }
212
213 /* This function converts originial pages' profiling data to destination pages'
214  * profiling data.
215  * The parameter current_ptr indicates the current position in the destination 
216  * pages.
217  * Note that there could be objects that across pages. In such cases, there are 
218  * multiple orig/to pages are closed and all these to pages' profiling data 
219  * should be properly updated.
220  */
221 INLINE static void samplingDataConvert(void * current_ptr) {
222   if(gc_cache_revise_information.to_page_end_va<current_ptr) {
223     // multiple pages are closed
224     samplingDataConvertMultiple(current_ptr);
225   } else {
226     unsigned INTPTR tmp_factor=(unsigned INTPTR)(current_ptr-gc_cache_revise_information.to_page_start_va);
227     if(tmp_factor) {
228       unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
229       unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
230       int * newtable=&gccachesamplingtbl_r[topage];
231       int * oldtable=&gccachesamplingtbl[oldpage];
232   
233       for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
234         (*newtable)=((*newtable)+(*oldtable)*tmp_factor);
235         newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
236         oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
237       }
238     }
239   }
240
241
242 /*
243  */
244 INLINE static void completePageConvert(void * origptr, void * toptr, void * current_ptr) {
245   bool closeToPage=(unsigned int)(toptr)>=(unsigned int)(gc_cache_revise_information.to_page_end_va);
246   bool closeOrigPage=(unsigned int)(origptr)>=(unsigned int)(gc_cache_revise_information.orig_page_end_va);
247   if(closeToPage||closeOrigPage) {
248     // end of one or more orig/to page
249     // compute the impact of the original page(s) for the desitination page(s)
250     samplingDataConvert(current_ptr);
251     // prepare for an new orig page
252     unsigned INTPTR tmp_index=((unsigned INTPTR)(origptr-gcbaseva))/BAMBOO_PAGE_SIZE;
253     gc_cache_revise_information.orig_page_start_va=origptr;
254     gc_cache_revise_information.orig_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(tmp_index+1);
255     gc_cache_revise_information.orig_page_index=tmp_index;
256     gc_cache_revise_information.to_page_start_va=toptr;
257     if(closeToPage) {
258       unsigned INTPTR to_index=((unsigned INTPTR)(toptr-gcbaseva))/BAMBOO_PAGE_SIZE;
259       gc_cache_revise_information.to_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(to_index+1);
260       gc_cache_revise_information.to_page_index=to_index;
261     }
262   }
263
264
265 void cacheAdapt_gc(bool isgccachestage);
266 void cacheAdapt_master();
267 void cacheAdapt_mutator();
268 void cacheAdapt_phase_client();
269 void cacheAdapt_phase_master();
270 void gc_output_cache_sampling();
271 void gc_output_cache_sampling_r();
272
273 #ifdef GC_CACHE_SAMPLING
274 // enable the timer interrupt
275 #define CACHEADAPT_ENABLE_TIMER() \
276   { \
277     bamboo_tile_timer_set_next_event(GC_TILE_TIMER_EVENT_SETTING); \
278     bamboo_unmask_timer_intr(); \
279     bamboo_dtlb_sampling_process(); \
280   }
281 #else
282 #define CACHEADAPT_ENABLE_TIMER() 
283 #endif
284 // disable the TILE_TIMER interrupt
285 #define CACHEADAPT_DISABLE_TIMER() bamboo_mask_timer_intr() 
286
287 #ifdef GC_CACHE_SAMPLING
288 // reset the sampling arrays
289 #define CACHEADAPT_SAMPING_RESET()  bamboo_dtlb_sampling_reset()
290 #else // GC_CACHE_SAMPING
291 #define CACHEADAPT_SAMPING_RESET() 
292 #endif
293
294 #define CACHEADAPT_SAMPLING_DATA_REVISE_INIT(o,t) \
295   samplingDataReviseInit((o),(t))
296 #define CACHEADAPT_SAMPLING_DATA_CONVERT(p) samplingDataConvert((p))
297 #define CACHEADAPT_COMPLETE_PAGE_CONVERT(o, t, p) \
298   completePageConvert((o), (t), (p));
299
300 #define CACHEADAPT_GC(b) cacheAdapt_gc(b)
301 #define CACHEADAPT_MASTER() cacheAdapt_master()
302 #define CACHEADAPT_PHASE_CLIENT() cacheAdapt_phase_client()
303 #define CACHEADAPT_PHASE_MASTER() cacheAdapt_phase_master()
304
305 #ifdef GC_CACHE_ADAPT_OUTPUT
306 #define CACHEADAPT_OUTPUT_CACHE_SAMPLING() gc_output_cache_sampling()
307 #define CACHEADAPT_OUTPUT_CACHE_SAMPLING_R() gc_output_cache_sampling_r()
308 #else
309 #define CACHEADAPT_OUTPUT_CACHE_SAMPLING()
310 #define CACHEADAPT_OUTPUT_CACHE_SAMPLING_R() 
311 #endif
312
313 #ifdef GC_CACHE_ADAPT_OUTPUT_POLICY
314 #ifdef MGC_SPEC
315 #define CACHEADAPT_OUTPUT_CACHE_POLICY() \
316   { \
317     if(1) { \
318       bamboo_output_cache_policy(); \
319     } \
320   }
321 #else // MGC_SPEC
322 #define CACHEADAPT_OUTPUT_CACHE_POLICY() bamboo_output_cache_policy()
323 #endif // MGC_SPEC
324 #else // GC_CACHE_ADAPT_OUTPUT_POLICY
325 #define CACHEADAPT_OUTPUT_CACHE_POLICY() 
326 #endif // GC_CACHE_ADAPT_OUTPUT
327
328 #else // GC_CACHE_ADAPT
329 #define CACHEADAPT_ENABLE_TIMER() 
330 #define CACHEADAPT_DISABLE_TIMER() 
331 #define CACHEADAPT_SAMPING_RESET()
332 #define CACHEADAPT_SAMPLING_DATA_REVISE_INIT(o,t) 
333 #define CACHEADAPT_SAMPLING_DATA_CONVERT(p) 
334 #define CACHEADAPT_COMPLETE_PAGE_CONVERT(o, t, p, b) 
335 #define CACHEADAPT_GC(b)
336 #define CACHEADAPT_MASTER()
337 #define CACHEADAPT_PHASE_CLIENT() 
338 #define CACHEADAPT_PHASE_MASTER() 
339 #define CACHEADAPT_OUTPUT_CACHE_SAMPLING()
340 #define CACHEADAPT_OUTPUT_CACHE_SAMPLING_R() 
341 #define CACHEADAPT_OUTPUT_CACHE_POLICY() 
342 #endif // GC_CACHE_ADAPT
343 #else // MULTICORE_GC
344 #define CACHEADAPT_ENABLE_TIMER() 
345 #define CACHEADAPT_DISABLE_TIMER()
346 #endif // MULTICORE_GC
347
348 #endif // BAMBOO_MULTICORE_CACHE_H