}
}
-#if 0
-#define GC_CACHE_ADAPT_OVERLOAD_THRESHOLD 10
-// record the worklocad of the hottestcore into core2heavypages
-#define CACHEADAPT_RECORD_PAGE_WORKLOAD(hottestcore,totalfreq,hotfreq,remoteaccess,tmp_p) \
- { \
- workload[hottestcore] += (totalfreq); \
- total_workload += (totalfreq); \
- unsigned long long remoteaccess = (totalfreq) - (hotfreq); \
- unsigned int index = (unsigned int)core2heavypages[hottestcore][0]; \
- core2heavypages[hottestcore][3*index+3] = (remoteaccess); \
- core2heavypages[hottestcore][3*index+2] = (totalfreq); \
- core2heavypages[hottestcore][3*index+1] = (unsigned long long)((tmp_p)-1); \
- core2heavypages[hottestcore][0]++; \
- }
-
-void gc_quicksort(unsigned long long *array,unsigned int left,unsigned int right,unsigned int offset) {
- unsigned int pivot = 0;;
- unsigned int leftIdx = left;
- unsigned int rightIdx = right;
- if((right-left+1) >= 1) {
- pivot = (left+right)/2;
- while((leftIdx <= pivot) && (rightIdx >= pivot)) {
- unsigned long long pivotValue = array[pivot*3-offset];
- while((array[leftIdx*3-offset] > pivotValue) && (leftIdx <= pivot)) {
- leftIdx++;
- }
- while((array[rightIdx*3-offset] < pivotValue) && (rightIdx >= pivot)) {
- rightIdx--;
- }
- // swap [leftIdx] & [rightIdx]
- for(int k = 0; k < 3; k++) {
- unsigned long long tmp = array[3*rightIdx-k];
- array[3*rightIdx-k] = array[3*leftIdx-k];
- array[3*leftIdx-k] = tmp;
- }
- leftIdx++;
- rightIdx--;
- if((leftIdx-1) == pivot) {
- pivot = rightIdx = rightIdx + 1;
- } else if((leftIdx+1) == pivot) {
- pivot = leftIdx = leftIdx-1;
- }
- }
- gc_quicksort(array, left, pivot-1, offset);
- gc_quicksort(array, pivot+1, right, offset);
- }
- return;
-}
-
-INLINE int cacheAdapt_h4h_remote_accesses(unsigned long long workload_threshold,unsigned long long ** core2heavypages, unsigned long long * workload,int i) {
- int j = 1;
- unsigned int index = (unsigned int)core2heavypages[i][0];
- if(workload[i] > workload_threshold) {
- // sort according to the remoteaccess
- gc_quicksort(&core2heavypages[i][0], 1, index, 0);
- while((workload[i] > workload_threshold) && (j<index*3)) {
- // hfh those pages with more remote accesses
- bamboo_cache_policy_t policy = {0};
- policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
- *((unsigned int*)core2heavypages[i][j]) = policy.word;
- workload[i] -= core2heavypages[i][j+1];
- j += 3;
- }
- }
- return j;
-}
-
-// Every page cached on the core that accesses it the most.
-// Check to see if any core's pages total more accesses than threshold
-// GC_CACHE_ADAPT_OVERLOAD_THRESHOLD. If so, find the pages with the
-// most remote accesses and hash for home them until we get below
-// GC_CACHE_ADAPT_OVERLOAD_THRESHOLD
-int cacheAdapt_policy_overload(int coren){
- unsigned int page_index = 0;
- VA page_sva = gcbaseva;
- unsigned int page_num = BAMBOO_SHARED_MEM_SIZE/BAMBOO_PAGE_SIZE;
- unsigned int numchanged = 0;
- int * tmp_p = gccachepolicytbl+1;
- unsigned long long workload[NUMCORESACTIVE];
- memset(workload, 0, NUMCORESACTIVE*sizeof(unsigned long long));
- unsigned long long total_workload = 0;
- unsigned long long core2heavypages[NUMCORESACTIVE][page_num*3+1];
- memset(core2heavypages,0,sizeof(unsigned long long)*(page_num*3+1)*NUMCORESACTIVE);
- for(page_index = 0; page_sva < gctopva; page_index++) {
- bamboo_cache_policy_t policy = {0};
- unsigned int hottestcore = 0;
- unsigned long long totalfreq = 0;
- unsigned int hotfreq = 0;
- CACHEADAPT_FIND_HOTTEST_CORE_W_TOTALFREQ(page_index,hottestcore,hotfreq,totalfreq);
- // Decide the cache strategy for this page
- // If decide to adapt a new cache strategy, write into the shared block of
- // the gcsharedsamplingtbl. The mem recording information that has been
- // written is enough to hold the information.
- // Format: page start va + cache strategy(hfh/(host core+[x,y]))
- if(hotfreq != 0) {
- totalfreq/=BAMBOO_PAGE_SIZE;
- hotfreq/=BAMBOO_PAGE_SIZE;
- // locally cache the page in the hottest core
- CACHEADAPT_POLICY_SET_HOST_CORE(policy, hottestcore);
- CACHEADAPT_CHANGE_POLICY_4_PAGE(tmp_p,page_index,policy,numchanged);
- CACHEADAPT_RECORD_PAGE_WORKLOAD(hottestcore,totalfreq,hotfreq,remoteaccess,tmp_p);
- }
- page_sva += BAMBOO_PAGE_SIZE;
- }
-
- unsigned long long workload_threshold=total_workload/GC_CACHE_ADAPT_OVERLOAD_THRESHOLD;
- // Check the workload of each core
- for(int i = 0; i < NUMCORESACTIVE; i++) {
- cacheAdapt_h4h_remote_accesses(workload_threshold,core2heavypages,workload,i);
- }
-
- return numchanged;
-}
-
-#define GC_CACHE_ADAPT_ACCESS_THRESHOLD 70
-#define GC_CACHE_ADAPT_CROWD_THRESHOLD 20
-// Every page cached on the core that accesses it the most.
-// Check to see if any core's pages total more accesses than threshold
-// GC_CACHE_ADAPT_OVERLOAD_THRESHOLD. If so, find the pages with the
-// most remote accesses and hash for home them until we get below
-// GC_CACHE_ADAPT_OVERLOAD_THRESHOLD.
-// Sort pages based on activity....
-// If more then GC_CACHE_ADAPT_ACCESS_THRESHOLD% of the accesses for a
-// core's pages are from more than GC_CACHE_ADAPT_CROWD_THRESHOLD pages,
-// then start hfh these pages(selecting the ones with the most remote
-// accesses first or fewest local accesses) until we get below
-// GC_CACHE_ADAPT_CROWD_THRESHOLD pages.
-int cacheAdapt_policy_crowd(int coren){
- unsigned int page_index = 0;
- VA page_sva = gcbaseva;
- unsigned int page_num = BAMBOO_SHARED_MEM_SIZE/BAMBOO_PAGE_SIZE;
- unsigned int numchanged = 0;
- int * tmp_p = gccachepolicytbl+1;
- unsigned long long workload[NUMCORESACTIVE];
- memset(workload, 0, NUMCORESACTIVE*sizeof(unsigned long long));
- unsigned long long total_workload = 0;
- unsigned long long core2heavypages[NUMCORESACTIVE][page_num*3+1];
- memset(core2heavypages,0,sizeof(unsigned long long)*(page_num*3+1)*NUMCORESACTIVE);
- for(page_index = 0; page_sva < gctopva; page_index++) {
- bamboo_cache_policy_t policy = {0};
- unsigned int hottestcore = 0;
- unsigned long long totalfreq = 0;
- unsigned int hotfreq = 0;
- CACHEADAPT_FIND_HOTTEST_CORE_W_TOTALFREQ(page_index,hottestcore,hotfreq,totalfreq);
- // Decide the cache strategy for this page
- // If decide to adapt a new cache strategy, write into the shared block of
- // the gcsharedsamplingtbl. The mem recording information that has been
- // written is enough to hold the information.
- // Format: page start va + cache strategy(hfh/(host core+[x,y]))
- if(hotfreq != 0) {
- totalfreq/=BAMBOO_PAGE_SIZE;
- hotfreq/=BAMBOO_PAGE_SIZE;
- // locally cache the page in the hottest core
- CACHEADAPT_POLICY_SET_HOST_CORE(policy, hottestcore);
- CACHEADAPT_CHANGE_POLICY_4_PAGE(tmp_p,page_index,policy,numchanged);
- CACHEADAPT_RECORD_PAGE_WORKLOAD(hottestcore,totalfreq,hotfreq,remoteaccess,tmp_p);
- }
- page_sva += BAMBOO_PAGE_SIZE;
- }
-
- unsigned long long workload_threshold=total_workload/GC_CACHE_ADAPT_OVERLOAD_THRESHOLD;
- // Check the workload of each core
- for(int i = 0; i < NUMCORESACTIVE; i++) {
- unsigned int index=(unsigned int)core2heavypages[i][0];
- int j=cacheAdapt_h4h_remote_accesses(workload_threshold,core2heavypages,workload,i);
- // Check if the accesses are crowded on few pages
- // sort according to the total access
-inner_crowd:
- gc_quicksort(&core2heavypages[i][0], j/3+1, index, 1);
- unsigned long long threshold=GC_CACHE_ADAPT_ACCESS_THRESHOLD*workload[i]/100;
- int num_crowded = 0;
- unsigned long long t_workload = 0;
- do {
- t_workload += core2heavypages[i][j+num_crowded*3+1];
- num_crowded++;
- } while(t_workload < threshold);
- // num_crowded <= GC_CACHE_ADAPT_CROWD_THRESHOLD and if there are enough
- // items, it is always == GC_CACHE_ADAPT_CROWD_THRESHOLD
- if(num_crowded > GC_CACHE_ADAPT_CROWD_THRESHOLD) {
- // need to hfh these pages
- // sort the pages according to remote access
- gc_quicksort(&core2heavypages[i][0], j/3+1, j/3+num_crowded, 0);
- // h4h those pages with more remote accesses
- bamboo_cache_policy_t policy = {0};
- policy.cache_mode = BAMBOO_CACHE_MODE_HASH;
- *((unsigned int*)core2heavypages[i][j]) = policy.word;
- workload[i] -= core2heavypages[i][j+1];
- t_workload -= core2heavypages[i][j+1];
- j += 3;
- threshold = GC_CACHE_ADAPT_ACCESS_THRESHOLD*workload[i]/100;
- goto inner_crowd;
- }
- }
-
- return numchanged;
-}
-#endif
-
unsigned int cacheAdapt_decision(int coren) {
BAMBOO_CACHE_MF();
// check the statistic data
cacheAdapt_policy_hottest(coren);
#elif defined GC_CACHE_ADAPT_POLICY4
cacheAdapt_policy_dominate(coren);
-//#elif defined GC_CACHE_ADAPT_POLICY5
-// cacheAdapt_policy_overload(coren);
-//#elif defined GC_CACHE_ADAPT_POLICY6
-// cacheAdapt_policy_crowd(coren);
#endif
}
}
}
+// Cache adapt phase process for clients
void cacheAdapt_phase_client() {
WAITFORGCPHASE(CACHEPOLICYPHASE);
GC_PRINTF("Start cachepolicy phase\n");
extern unsigned long long gc_output_cache_policy_time;
+// Cache adpat phase process for the master
void cacheAdapt_phase_master() {
GCPROFILE_ITEM();
unsigned long long tmpt = BAMBOO_GET_EXE_TIME();
}
}
+// output original cache sampling data for each page
void gc_output_cache_sampling() {
//extern volatile bool gc_profile_flag;
//if(!gc_profile_flag) return;
printf("=================\n");
}
+// output revised cache sampling data for each page after compaction
void gc_output_cache_sampling_r() {
//extern volatile bool gc_profile_flag;
//if(!gc_profile_flag) return;
if(accesscore!=0) {
for(int i = 0; i < NUMCORESACTIVE; i++) {
int * local_tbl = (int *)((void *)gccachesamplingtbl_r+size_cachesamplingtbl_local_r*i);
- int freq = local_tbl[page_index]/BAMBOO_PAGE_SIZE;
+ int freq = local_tbl[page_index]; ///BAMBOO_PAGE_SIZE;
sumdata[accesscore-1][i]+=freq;
}
}
#include "multicoregarbage.h"
#ifdef GC_CACHE_ADAPT
-#define GC_CACHE_SAMPLING_UNIT 0x40000 //100000 //000
-#define GC_TILE_TIMER_EVENT_SETTING (GC_CACHE_SAMPLING_UNIT) //100000 //000
+// sampling unit to compute access frequency, this should be consistent all the
+// time.
+#define GC_CACHE_SAMPLING_UNIT 0x80000
+// freqeuency to trigger timer interrupt
+#define GC_TILE_TIMER_EVENT_SETTING 10000000
+// data structure to record policy information for a page
// should be consistent with multicoreruntime.h
typedef union
{
unsigned int word;
struct
{
- // policy type
+ // policy type, should be enough to accommodate all 4 possible polices
unsigned int cache_mode : 3;
// Reserved.
unsigned int __reserved_0 : 5;
};
} bamboo_cache_policy_t;
-#define BAMBOO_CACHE_MODE_LOCAL 1
-#define BAMBOO_CACHE_MODE_HASH 2
-#define BAMBOO_CACHE_MODE_NONE 3
-#define BAMBOO_CACHE_MODE_COORDS 4
+#define BAMBOO_CACHE_MODE_LOCAL 1 // locally cached
+#define BAMBOO_CACHE_MODE_HASH 2 // hash-for-home
+#define BAMBOO_CACHE_MODE_NONE 3 // no caching
+#define BAMBOO_CACHE_MODE_COORDS 4 // cached on a specific core
+// data structure to hold page information while calculating revised sampling
+// info during compaction
typedef struct gc_cache_revise_info {
- void * orig_page_start_va;
+ // the start address in current original page to be compacted to current
+ // destination page
+ void * orig_page_start_va;
+ // the end of current original page to be compacted
void * orig_page_end_va;
+ // the index of current original page
unsigned int orig_page_index;
+ // the start address in current destination page to where the current original
+ // page is compacted
void * to_page_start_va;
+ // the end of current destination page
void * to_page_end_va;
+ // the index of current destination page
unsigned int to_page_index;
- unsigned int revised_sampling[NUMCORESACTIVE];
} gc_cache_revise_info_t;
+// global variable holding page information to compute revised sampling info
extern gc_cache_revise_info_t gc_cache_revise_information;
+/* This function initialize the gc_cache_revise_information. It should be
+ * invoked before we start compaction.
+ */
INLINE static void samplingDataReviseInit(struct moveHelper * orig,struct moveHelper * to) {
+ // initialize the destination page info
gc_cache_revise_information.to_page_start_va=to->ptr;
unsigned int toindex=(unsigned INTPTR)(to->base-gcbaseva)/BAMBOO_PAGE_SIZE;
gc_cache_revise_information.to_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(toindex+1);
gc_cache_revise_information.to_page_index=toindex;
+ // initilaize the original page info
+ unsigned int origindex=((unsigned INTPTR)(orig->base-gcbaseva))/BAMBOO_PAGE_SIZE;
gc_cache_revise_information.orig_page_start_va=orig->ptr;
- gc_cache_revise_information.orig_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(((unsigned INTPTR)(orig->ptr-gcbaseva))/BAMBOO_PAGE_SIZE+1);
- gc_cache_revise_information.orig_page_index=((unsigned INTPTR)(orig->base-gcbaseva))/BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.orig_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(origindex+1);
+ gc_cache_revise_information.orig_page_index=origindex;
}
-INLINE static void samplingDataConvert(void * current_ptr) {
- unsigned INTPTR tmp_factor=(unsigned INTPTR)(current_ptr-gc_cache_revise_information.to_page_start_va);
+/* This function computes the revised profiling data of the first closed destination
+ * page of an object that acrosses multiple pages
+ */
+INLINE static void firstPageConvert(bool origclosefirst, unsigned INTPTR main_factor, unsigned INTPTR delta_factor) {
unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
int * newtable=&gccachesamplingtbl_r[topage];
int * oldtable=&gccachesamplingtbl[oldpage];
-
+ // compute the revised profiling info for the start destination page
+ if(origclosefirst) {
+ // the start original page closes first, now compute the revised profiling
+ // info for the start destination page.
+ // The start destination page = the rest of the start original page +
+ // delta_fator from the next original page
+ int * oldtable_next=&gccachesamplingtbl[oldpage+1];
+ for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
+ (*newtable)=((*newtable)+(*oldtable)*main_factor+(*oldtable_next)*delta_factor);
+ newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
+ oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
+ oldtable_next=(int*) (((char *)oldtable_next)+size_cachesamplingtbl_local);
+ }
+ // close the start original page
+ gc_cache_revise_information.orig_page_start_va+=main_factor+delta_factor;
+ gc_cache_revise_information.orig_page_end_va+=BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.orig_page_index++;
+ } else {
+ // the start destination page closes first, now compute the revised
+ // profiling info for it.
+ for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
+ (*newtable)=((*newtable)+(*oldtable)*main_factor);
+ newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
+ oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
+ }
+ // record the new start of the original page
+ gc_cache_revise_information.orig_page_start_va+=main_factor;
+ }
+ // close the start original page and destination page
+ gc_cache_revise_information.to_page_start_va=gc_cache_revise_information.to_page_end_va;
+ gc_cache_revise_information.to_page_end_va+=BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.to_page_index++;
+}
+
+/* This function computes the revised profiling info for closed destination
+ * pages that are occupied by one object that acrosses multiple pages.
+ * the destination page = main_factor from the first unclosed original page
+ * + delta_factor from the next unclosed original page
+ */
+INLINE static void restClosedPageConvert(void * current_ptr, unsigned INTPTR main_factor, unsigned INTPTR delta_factor) {
+ while(gc_cache_revise_information.to_page_end_va<=current_ptr) {
+ unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
+ unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
+ int *newtable=&gccachesamplingtbl_r[topage];
+ int *oldtable=&gccachesamplingtbl[oldpage];
+ int *oldtable_next=&gccachesamplingtbl[oldpage+1];
+
+ for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
+ (*newtable)=((*newtable)+(*oldtable)*main_factor+(*oldtable_next)*delta_factor);
+ newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
+ oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
+ oldtable_next=(int*) (((char *)oldtable_next)+size_cachesamplingtbl_local);
+ }
+
+ // close the original page and the destination page
+ gc_cache_revise_information.orig_page_start_va+=BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.orig_page_end_va+=BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.orig_page_index++;
+ gc_cache_revise_information.to_page_start_va=gc_cache_revise_information.to_page_end_va;
+ gc_cache_revise_information.to_page_end_va+=BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.to_page_index++;
+ }
+}
+
+/* This function computes the revised profiling info for the last
+ * destination page of an object that acrosses multiple pages.
+ */
+INLINE static void lastPageConvert(void * current_ptr) {
+ unsigned INTPTR to_factor=current_ptr-gc_cache_revise_information.to_page_start_va;
+ unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
+ unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
+ int *newtable=&gccachesamplingtbl_r[topage];
+ int *oldtable=&gccachesamplingtbl[oldpage];
+
for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
- (*newtable)=((*newtable)+(*oldtable)*tmp_factor);
+ (*newtable)=((*newtable)+(*oldtable)*to_factor);
newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
}
-}
+ // do not need to set gc_cache_revise_information here for the last
+ // original/destination page as it will be set in completePageConvert()
+}
+
+/* This function converts multiple original pages profiling data to multiple
+ * destination pages' profiling data
+ */
+INLINE static void samplingDataConvertMultiple(void * current_ptr) {
+ // first decide which page close first: original or destination?
+ unsigned INTPTR to_factor=(unsigned INTPTR)(gc_cache_revise_information.to_page_end_va-gc_cache_revise_information.to_page_start_va);
+ unsigned INTPTR orig_factor=(unsigned INTPTR)(gc_cache_revise_information.orig_page_end_va-gc_cache_revise_information.orig_page_start_va);
+ bool origclosefirst=to_factor>orig_factor;
+ unsigned INTPTR delta_factor=(origclosefirst)?(to_factor-orig_factor):(orig_factor-to_factor);
+ unsigned INTPTR main_factor=(origclosefirst)?orig_factor:to_factor;
-INLINE static void completePageConvert(struct moveHelper * orig,struct moveHelper * to, void * current_ptr,bool closeToPage) {
- void *ptr;
- void *tocompare;
- if(closeToPage) {
- ptr=to->ptr;
- tocompare=gc_cache_revise_information.to_page_end_va;
+ // compute the revised profiling info for the start destination page
+ firstPageConvert(origclosefirst, main_factor, delta_factor);
+ // update main_factor/delta_factor
+ if(origclosefirst) {
+ // for the following destination pages that are fully used:
+ // the destination page = (page_size-delta_factor) from the
+ // first unclosed original page + delta_factor
+ // from the next unclosed original page
+ // we always use main_factor to represent the factor from the first
+ // unclosed original page
+ main_factor=BAMBOO_PAGE_SIZE-delta_factor;
} else {
- ptr=orig->ptr;
- tocompare=gc_cache_revise_information.orig_page_end_va;
+ // for the following destination pages that are fully used:
+ // the destination page = delta_factor from the first unclosed original
+ // page + (page_size-delta_factor) from the next
+ // unclosed original page
+ // we always use main_factor to represent the factor from the first
+ // unclosed original page
+ main_factor=delta_factor;
+ delta_factor=BAMBOO_PAGE_SIZE-delta_factor;
}
- if((unsigned int)ptr>=(unsigned int)tocompare) {
- // end of an orig/to page
- // compute the impact of this page for the new page
+
+ // compute the revised profiling info for the following closed destination
+ // pages
+ restClosedPageConvert(current_ptr, main_factor, delta_factor);
+
+ // compute the revised profiling info for the last destination page if needed
+ lastPageConvert(current_ptr);
+}
+
+/* This function converts originial pages' profiling data to destination pages'
+ * profiling data.
+ * The parameter current_ptr indicates the current position in the destination
+ * pages.
+ * Note that there could be objects that across pages. In such cases, there are
+ * multiple orig/to pages are closed and all these to pages' profiling data
+ * should be properly updated.
+ */
+INLINE static void samplingDataConvert(void * current_ptr) {
+ if(gc_cache_revise_information.to_page_end_va<current_ptr) {
+ // multiple pages are closed
+ samplingDataConvertMultiple(current_ptr);
+ } else {
+ unsigned INTPTR tmp_factor=(unsigned INTPTR)(current_ptr-gc_cache_revise_information.to_page_start_va);
+ if(tmp_factor) {
+ unsigned INTPTR topage=gc_cache_revise_information.to_page_index;
+ unsigned INTPTR oldpage=gc_cache_revise_information.orig_page_index;
+ int * newtable=&gccachesamplingtbl_r[topage];
+ int * oldtable=&gccachesamplingtbl[oldpage];
+
+ for(int tt = 0; tt < NUMCORESACTIVE; tt++) {
+ (*newtable)=((*newtable)+(*oldtable)*tmp_factor);
+ newtable=(int*)(((char *)newtable)+size_cachesamplingtbl_local_r);
+ oldtable=(int*) (((char *)oldtable)+size_cachesamplingtbl_local);
+ }
+ }
+ }
+}
+
+/*
+ */
+INLINE static void completePageConvert(void * origptr, void * toptr, void * current_ptr) {
+ bool closeToPage=(unsigned int)(toptr)>=(unsigned int)(gc_cache_revise_information.to_page_end_va);
+ bool closeOrigPage=(unsigned int)(origptr)>=(unsigned int)(gc_cache_revise_information.orig_page_end_va);
+ if(closeToPage||closeOrigPage) {
+ // end of one or more orig/to page
+ // compute the impact of the original page(s) for the desitination page(s)
samplingDataConvert(current_ptr);
// prepare for an new orig page
- unsigned INTPTR tmp_index=((unsigned INTPTR)(orig->ptr-gcbaseva))/BAMBOO_PAGE_SIZE;
- gc_cache_revise_information.orig_page_start_va=orig->ptr;
+ unsigned INTPTR tmp_index=((unsigned INTPTR)(origptr-gcbaseva))/BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.orig_page_start_va=origptr;
gc_cache_revise_information.orig_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(tmp_index+1);
gc_cache_revise_information.orig_page_index=tmp_index;
- gc_cache_revise_information.to_page_start_va=to->ptr;
+ gc_cache_revise_information.to_page_start_va=toptr;
if(closeToPage) {
- gc_cache_revise_information.to_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(((unsigned INTPTR)(to->ptr-gcbaseva))/BAMBOO_PAGE_SIZE+1);
- gc_cache_revise_information.to_page_index=((unsigned INTPTR)(to->ptr-gcbaseva))/BAMBOO_PAGE_SIZE;
+ unsigned INTPTR to_index=((unsigned INTPTR)(toptr-gcbaseva))/BAMBOO_PAGE_SIZE;
+ gc_cache_revise_information.to_page_end_va=gcbaseva+BAMBOO_PAGE_SIZE*(to_index+1);
+ gc_cache_revise_information.to_page_index=to_index;
}
}
}
#define CACHEADAPT_SAMPLING_DATA_REVISE_INIT(o,t) \
samplingDataReviseInit((o),(t))
#define CACHEADAPT_SAMPLING_DATA_CONVERT(p) samplingDataConvert((p))
-#define CACHEADAPT_COMPLETE_PAGE_CONVERT(o, t, p, b) \
- completePageConvert((o), (t), (p), (b));
+#define CACHEADAPT_COMPLETE_PAGE_CONVERT(o, t, p) \
+ completePageConvert((o), (t), (p));
#define CACHEADAPT_GC(b) cacheAdapt_gc(b)
#define CACHEADAPT_MASTER() cacheAdapt_master()
#ifdef MGC_SPEC
#define CACHEADAPT_OUTPUT_CACHE_POLICY() \
{ \
- if(gc_profile_flag) { \
+ if(1) { \
bamboo_output_cache_policy(); \
} \
}
unsigned int tloads = 0;
for(int i = 0; i < NUMCORES4GC; i++) {
tloads += gcloads[i];
+ //tprintf("load: %d %d \n", gcloads[i], i);
}
heaptop = gcbaseva + tloads;
orig->localblocknum = 0;
orig->ptr=orig->base = to->base;
orig->bound = orig->base + BLOCKSIZE(orig->localblocknum);
+#ifdef GC_CACHE_ADAPT
+ to->pagebound=to->base+BAMBOO_PAGE_SIZE;
+ orig->pagebound=orig->base+BAMBOO_PAGE_SIZE;
+#endif
}
void getSpaceLocally(struct moveHelper *to) {
BASEPTR(to->base,BAMBOO_NUM_OF_CORE, to->localblocknum);
to->ptr=to->base;
to->bound = to->base + BLOCKSIZE(to->localblocknum);
+#ifdef GC_CACHE_ADAPT
+ to->pagebound=to->base+BAMBOO_PAGE_SIZE;
+#endif
}
//This function is called on the master core only...and typically by
BLOCKINDEX(globalblocknum, to->ptr);
to->base = gcbaseva + OFFSET2BASEVA(globalblocknum);
to->bound = gcbaseva + BOUNDPTR(globalblocknum);
+#ifdef GC_CACHE_ADAPT
+ to->pagebound=(void *)((int)((int)(to->ptr)&(~(BAMBOO_PAGE_SIZE-1)))+BAMBOO_PAGE_SIZE);
+#endif
}
void getSpace(struct moveHelper *to, unsigned int minimumbytes) {
//Only send the message once
senttopmessage=true;
}
- unsigned int minimumbytes=compactblocks(orig, to);
-
+ unsigned int minimumbytes=COMPACTUNITS(orig, to);
if (orig->ptr==orig->bound) {
//need more data to compact
//increment the core
BASEPTR(orig->base,BAMBOO_NUM_OF_CORE, orig->localblocknum);
orig->ptr=orig->base;
orig->bound = orig->base + BLOCKSIZE(orig->localblocknum);
+#ifdef GC_CACHE_ADAPT
+ orig->pagebound=orig->base+BAMBOO_PAGE_SIZE;
+#endif
if (orig->base >= gcbaseva+BAMBOO_SHARED_MEM_SIZE)
break;
}
return NULL;
}
+#ifdef GC_CACHE_ADAPT
+/* To compute access rate per pages, we need to compact to page boundary
+ * instead of block boundary
+ */
+unsigned int compactpages(struct moveHelper * orig, struct moveHelper * to) {
+ void *toptrinit=to->ptr;
+ void *toptr=toptrinit;
+ void *tobound=to->bound;
+ void *topagebound=to->pagebound;
+ void *origptr=orig->ptr;
+ void *origpagebound=orig->pagebound;
+ unsigned INTPTR origendoffset=ALIGNTOTABLEINDEX((unsigned INTPTR)(origpagebound-gcbaseva));
+ unsigned int objlength;
+ while((origptr<origpagebound)&&(toptr<topagebound)){
+ //Try to skip over stuff fast first
+ unsigned INTPTR offset=(unsigned INTPTR) (origptr-gcbaseva);
+ unsigned INTPTR arrayoffset=ALIGNTOTABLEINDEX(offset);
+ if (!gcmarktbl[arrayoffset]) {
+ do {
+ arrayoffset++;
+ if (arrayoffset>=origendoffset) {
+ //finished with a page...
+ origptr=origpagebound;
+ to->ptr=toptr;
+ orig->ptr=origptr;
+ orig->pagebound+=BAMBOO_PAGE_SIZE;
+ gccurr_heaptop-=(unsigned INTPTR)(toptr-toptrinit);
+ // close the last destination page
+ CACHEADAPT_COMPLETE_PAGE_CONVERT(origptr, toptr, toptr);
+ return 0;
+ }
+ } while(!gcmarktbl[arrayoffset]);
+ origptr=CONVERTTABLEINDEXTOPTR(arrayoffset);
+ }
+
+ //Scan more carefully next
+ objlength=getMarkedLength(origptr);
+
+ if (objlength!=NOTMARKED) {
+ unsigned int length=ALIGNSIZETOBYTES(objlength);
+
+ //code between this and next comment should be removed
+#ifdef GC_DEBUG
+ unsigned int size;
+ unsigned int type;
+ gettype_size(origptr, &type, &size);
+ size=((size-1)&(~(ALIGNMENTSIZE-1)))+ALIGNMENTSIZE;
+
+ if (size!=length) {
+ tprintf("BAD SIZE IN BITMAP: type=%u object=%x size=%u length=%u\n", type, origptr, size, length);
+ unsigned INTPTR alignsize=ALIGNOBJSIZE((unsigned INTPTR)(origptr-gcbaseva));
+ unsigned INTPTR hibits=alignsize>>4;
+ unsigned INTPTR lobits=(alignsize&15)<<1;
+ tprintf("hibits=%x lobits=%x\n", hibits, lobits);
+ tprintf("hi=%x lo=%x\n", gcmarktbl[hibits], gcmarktbl[hibits+1]);
+ }
+#endif
+ //end of code to remove
+
+ void *endtoptr=toptr+length;
+ if (endtoptr>tobound) {
+ gccurr_heaptop-=(unsigned INTPTR)(toptr-toptrinit);
+ to->ptr=tobound;
+ orig->ptr=origptr;
+ // close a destination page, update the revise profiling info
+ CACHEADAPT_COMPLETE_PAGE_CONVERT(origptr, tobound, toptr);
+ return length;
+ }
+ //good to move objects and update pointers
+ //tprintf("Decided to compact obj %x to %x\n", origptr, toptr);
+
+ gcmappingtbl[OBJMAPPINGINDEX(origptr)]=toptr;
+
+ origptr+=length;
+ toptr=endtoptr;
+ } else
+ origptr+=ALIGNMENTSIZE;
+ }
+ to->ptr=toptr;
+ orig->ptr=origptr;
+ orig->pagebound=(void *)((int)(((int)origptr)&(~(BAMBOO_PAGE_SIZE-1)))+BAMBOO_PAGE_SIZE);
+ to->pagebound=(void *)((int)(((int)toptr)&(~(BAMBOO_PAGE_SIZE-1)))+BAMBOO_PAGE_SIZE);
+ gccurr_heaptop-=(unsigned INTPTR)(toptr-toptrinit);
+ // close the last destination page
+ CACHEADAPT_COMPLETE_PAGE_CONVERT(origptr, toptr, toptr);
+ return 0;
+}
+
+#else
/* This function is performance critical... spend more time optimizing it */
unsigned int compactblocks(struct moveHelper * orig, struct moveHelper * to) {
void *endtoptr=toptr+length;
if (endtoptr>tobound) {
- gccurr_heaptop-=(unsigned INTPTR)(toptr-toptrinit);
+ gccurr_heaptop-=(unsigned INTPTR)(toptr-toptrinit);
to->ptr=tobound;
orig->ptr=origptr;
return length;
return 0;
}
+#endif
+
void compact() {
BAMBOO_ASSERT(COMPACTPHASE == gc_status_info.gcphase);
void * base; // base virtual address of current heap block
void * ptr; // current pointer into block
void * bound; // upper bound of current block
+#ifdef GC_CACHE_ADAPT
+ void * pagebound; // upper bound of current available page
+#endif
};
void initOrig_Dst(struct moveHelper * orig,struct moveHelper * to);
void compacthelper(struct moveHelper * orig,struct moveHelper * to);
-unsigned int compactblocks(struct moveHelper * orig,struct moveHelper * to);
void compact();
void compact_master(struct moveHelper * orig, struct moveHelper * to);
+#ifdef GC_CACHE_ADAPT
+unsigned int compactpages(struct moveHelper * orig,struct moveHelper * to);
+#define COMPACTUNITS(o,t) compactpages((o), (t))
+#else
+unsigned int compactblocks(struct moveHelper * orig,struct moveHelper * to);
+#define COMPACTUNITS(o,t) compactblocks((o), (t))
+#endif
#endif // MULTICORE_GC
#endif // BAMBOO_MULTICORE_GC_COMPACT_H
3, //MEMREQUEST, // 0xE0
3, //MEMRESPONSE, // 0xE1
#ifdef MULTICORE_GC
+ 1, //GCINVOKE
1, //GCSTARTPRE, // 0xE2
1, //GCSTARTINIT, // 0xE3
1, //GCSTART, // 0xE4
}
#ifdef MULTICORE_GC
+void processmsg_gcinvoke_I() {
+ BAMBOO_ASSERT(BAMBOO_NUM_OF_CORE==STARTUPCORE);
+ if(!gc_status_info.gcprocessing && !gcflag) {
+ gcflag = true;
+ gcprecheck = true;
+ for(int i = 0; i < NUMCORESACTIVE; i++) {
+ // reuse the gcnumsendobjs & gcnumreceiveobjs
+ gcnumsendobjs[0][i] = 0;
+ gcnumreceiveobjs[0][i] = 0;
+ }
+ for(int i = 0; i < NUMCORES4GC; i++) {
+ if(i != STARTUPCORE) {
+ if(BAMBOO_CHECK_SEND_MODE()) {
+ cache_msg_1_I(i,GCSTARTPRE);
+ } else {
+ send_msg_1_I(i,GCSTARTPRE);
+ }
+ }
+ }
+ }
+}
+
void processmsg_gcstartpre_I() {
// the first time to be informed to start gc
gcflag = true;
#ifdef MULTICORE_GC
// GC msgs
+ case GCINVOKE: {
+ processmsg_gcinvoke_I();
+ break;
+ }
+
case GCSTARTPRE: {
processmsg_gcstartpre_I();
break;
MEMREQUEST, // 0xE0
MEMRESPONSE, // 0xE1
#ifdef MULTICORE_GC
- GCSTARTPRE, // 0xE2
- GCSTARTINIT, // 0xE3
- GCSTART, // 0xE4
- GCSTARTCOMPACT, // 0xE5
- GCSTARTUPDATE, // 0xE6
- GCFINISHPRE, // 0xE7
- GCFINISHINIT, // 0xE8
- GCFINISHMARK, // 0xE9
- GCFINISHCOMPACT, // 0xEa
+ GCINVOKE, // 0xE2
+ GCSTARTPRE, // 0xE3
+ GCSTARTINIT, // 0xE4
+ GCSTART, // 0xE5
+ GCSTARTCOMPACT, // 0xE6
+ GCSTARTUPDATE, // 0xE7
+ GCFINISHPRE, // 0xE8
+ GCFINISHINIT, // 0xE9
+ GCFINISHMARK, // 0xEa
+ GCFINISHCOMPACT, // 0xEb
GCRETURNMEM,
- GCFINISHUPDATE, // 0xEb
- GCFINISH, // 0xEc
- GCMARKCONFIRM, // 0xEd
- GCMARKREPORT, // 0xEe
- GCMARKEDOBJ, // 0xEf
- GCMOVESTART, // 0xF0
- GCLOBJREQUEST, // 0xF1
- GCREQBLOCK,
+ GCFINISHUPDATE, // 0xEc
+ GCFINISH, // 0xEd
+ GCMARKCONFIRM, // 0xEe
+ GCMARKREPORT, // 0xEf
+ GCMARKEDOBJ, // 0xF0
+ GCMOVESTART, // 0xF1
+ GCLOBJREQUEST, // 0xF2
+ GCREQBLOCK,
GCGRANTBLOCK,
GCLOBJINFO, // 0xF2
#ifdef GC_PROFILE
#endif
}
+void CALL00(___System______gc____) {
+#ifdef MULTICORE_GC
+ if(BAMBOO_NUM_OF_CORE == STARTUPCORE) {
+ if(!gc_status_info.gcprocessing && !gcflag) {
+ gcflag = true;
+ gcprecheck = true;
+ for(int i = 0; i < NUMCORESACTIVE; i++) {
+ // reuse the gcnumsendobjs & gcnumreceiveobjs
+ gcnumsendobjs[0][i] = 0;
+ gcnumreceiveobjs[0][i] = 0;
+ }
+ for(int i = 0; i < NUMCORES4GC; i++) {
+ if(i != STARTUPCORE) {
+ send_msg_1_I(i,GCSTARTPRE);
+ }
+ }
+ }
+ } else {
+ // send msg to the startup core to start gc
+ send_msg_1(STARTUPCORE, GCINVOKE);
+ }
+#endif
+}
+
#ifdef D___System______printString____L___String___
void CALL01(___System______printString____L___String___,
struct ___String___ * ___s___) {