Add cache adaptive code to multicore gc and add support for System.gc()
authorjzhou <jzhou>
Sat, 2 Jul 2011 00:40:46 +0000 (00:40 +0000)
committerjzhou <jzhou>
Sat, 2 Jul 2011 00:40:46 +0000 (00:40 +0000)
Robust/src/Runtime/bamboo/multicorecache.c
Robust/src/Runtime/bamboo/multicorecache.h
Robust/src/Runtime/bamboo/multicoregarbage.c
Robust/src/Runtime/bamboo/multicoregccompact.c
Robust/src/Runtime/bamboo/multicoregccompact.h
Robust/src/Runtime/bamboo/multicoremsg.c
Robust/src/Runtime/bamboo/multicoremsg.h
Robust/src/Runtime/bamboo/multicoreruntime.c

index 061e96cd5da0b018f70c9004f37eeee45ee8ee7c..b3bfba1e4e980b6c02c20f99d6afd94d71eff209 100644 (file)
@@ -167,204 +167,6 @@ void cacheAdapt_policy_dominate(int coren){
   }
 }
 
-#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
@@ -377,10 +179,6 @@ unsigned int cacheAdapt_decision(int coren) {
   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
 }
 
@@ -401,6 +199,7 @@ void cacheAdapt_mutator() {
   }
 }
 
+// Cache adapt phase process for clients
 void cacheAdapt_phase_client() {
   WAITFORGCPHASE(CACHEPOLICYPHASE);
   GC_PRINTF("Start cachepolicy phase\n");
@@ -427,6 +226,7 @@ void cacheAdapt_phase_client() {
 
 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();
@@ -461,6 +261,7 @@ void cacheAdapt_phase_master() {
   }
 }
 
+// output original cache sampling data for each page
 void gc_output_cache_sampling() {
   //extern volatile bool gc_profile_flag;
   //if(!gc_profile_flag) return;
@@ -485,6 +286,7 @@ void gc_output_cache_sampling() {
   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;
@@ -517,7 +319,7 @@ void gc_output_cache_sampling_r() {
     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;
       }
     }
index f5dc3d60d5b35225c3135af11a0dafb3a8997d0b..57fc8a0dc8daaa32167bb43b03d798d07bacd35b 100644 (file)
@@ -7,16 +7,20 @@
 #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;
@@ -31,70 +35,229 @@ typedef union
   };
 } 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;
     }
   }
 } 
@@ -131,8 +294,8 @@ void gc_output_cache_sampling_r();
 #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()
@@ -151,7 +314,7 @@ void gc_output_cache_sampling_r();
 #ifdef MGC_SPEC
 #define CACHEADAPT_OUTPUT_CACHE_POLICY() \
   { \
-    if(gc_profile_flag) { \
+    if(1) { \
       bamboo_output_cache_policy(); \
     } \
   }
index ef73a360c24b4015aaef099abf22956c4609d503..8416a52731eee2af39fbfb1576c41fd98c01ac87 100644 (file)
@@ -247,6 +247,7 @@ int loadbalance() {
   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;
 
index 18e3bf8f954b0b5386cea62d68223dd965c7a5a7..394ea3aa990980e6a293b7a1196734eb9afd46a8 100644 (file)
@@ -28,6 +28,10 @@ void initOrig_Dst(struct moveHelper * orig,struct moveHelper * to) {
   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) {
@@ -36,6 +40,9 @@ 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
@@ -160,6 +167,9 @@ void getSpaceRemotely(struct moveHelper *to, unsigned int minimumbytes) {
   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) {
@@ -184,8 +194,7 @@ void compacthelper(struct moveHelper * orig,struct moveHelper * to) {
       //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
@@ -193,6 +202,9 @@ void compacthelper(struct moveHelper * orig,struct moveHelper * to) {
       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;
     }
@@ -349,6 +361,95 @@ void * gcfindSpareMem_I(unsigned INTPTR requiredmem, unsigned INTPTR desiredmem,
   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) {
@@ -404,7 +505,7 @@ 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;
@@ -425,6 +526,8 @@ unsigned int compactblocks(struct moveHelper * orig, struct moveHelper * to) {
   return 0;
 }
 
+#endif
+
 void compact() {
   BAMBOO_ASSERT(COMPACTPHASE == gc_status_info.gcphase);
   
index 0d56cfc832bc49d272c8bc855392b08f73064da8..8daf58f5a9744ce92d2903165514686155438764 100644 (file)
@@ -9,13 +9,22 @@ struct moveHelper {
   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
index 8deb797b0113ad118ffb2ee6834d0bffe1f02819..20b2bc9b7a1a8720952ffb25c31d0745e752c89f 100644 (file)
@@ -30,6 +30,7 @@ int msgsizearray[] = {
   3, //MEMREQUEST,            // 0xE0
   3, //MEMRESPONSE,           // 0xE1
 #ifdef MULTICORE_GC
+  1, //GCINVOKE
   1, //GCSTARTPRE,            // 0xE2
   1, //GCSTARTINIT,           // 0xE3
   1, //GCSTART,               // 0xE4
@@ -410,6 +411,28 @@ void processmsg_memresponse_I() {
 }
 
 #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;
@@ -887,6 +910,11 @@ processmsg:
 
 #ifdef MULTICORE_GC
     // GC msgs
+    case GCINVOKE: {
+      processmsg_gcinvoke_I();
+      break;
+    }
+
     case GCSTARTPRE: {
       processmsg_gcstartpre_I();
       break;
index 7f9fed18b6afb32efe67d899944989b798f117cf..0005e18043602dcfb4ccae2b2674d4edb20d2be9 100644 (file)
@@ -173,24 +173,25 @@ typedef enum {
   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
index 8f4a025c4e38e2f95059e8236c9be3d3096330c8..a7548dcb951ad78f8347764598ff535c6ace6772 100644 (file)
@@ -346,6 +346,30 @@ void CALL00(___System______resetgcprofileflag____) {
 #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___) {