changeset 166:6872a12a8688

Bug 2977: [REFACTORING][JDK 9] Add marking bitmap for ParNew GC at CMS Final Remark
author Yasumasa Suenaga <yasuenag@gmail.com>
date Thu, 02 Jun 2016 22:23:26 +0900
parents a51e5042a3d1
children 365f5563c84b
files agent/src/heapstats-engines/overrider.cpp agent/src/heapstats-engines/vmFunctions.cpp agent/src/heapstats-engines/vmFunctions.hpp agent/src/heapstats-engines/vmVariables.cpp agent/src/heapstats-engines/vmVariables.hpp
diffstat 5 files changed, 109 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/heapstats-engines/overrider.cpp	Thu Jun 02 22:23:18 2016 +0900
+++ b/agent/src/heapstats-engines/overrider.cpp	Thu Jun 02 22:23:26 2016 +0900
@@ -107,7 +107,7 @@
 DEFINE_OVERRIDE_FUNC_1(watcherThread);
 
 /*!
- * \brief Bitmap object for G1 GC.
+ * \brief Bitmap object for CMS and G1 GC.
  */
 TBitMapMarker *checkObjectMap = NULL;
 
@@ -893,7 +893,8 @@
  */
 void cleanupOverrider(void) {
   /* Cleanup. */
-  if (TVMVariables::getInstance()->getUseG1()) {
+  TVMVariables *vmVal = TVMVariables::getInstance();
+  if (vmVal->getUseCMS() || vmVal->getUseG1()) {
     delete checkObjectMap;
     checkObjectMap = NULL;
   }
@@ -939,6 +940,8 @@
         *needSnapShot = needSnapShotByCMSPhase;
         needSnapShotByCMSPhase = false;
       } else if (vmVal->getCMS_collectorState() == CMS_FINALMARKING) {
+        checkObjectMap->clear();
+
         /* switch hooking for CMS new generation. */
         switchOverrideFunction(cms_new_hook, true);
       }
@@ -1169,6 +1172,27 @@
 bool setupForCMS(void) {
   SELECT_HOOK_FUNCS(cms_new);
 
+  TVMVariables *vmVal = TVMVariables::getInstance();
+  const void *startAddr = vmVal->getYoungGenStartAddr();
+  const size_t youngSize = vmVal->getYoungGenSize();
+
+/* Create bitmap to check object collected flag. */
+#ifdef AVX
+    checkObjectMap = new TAVXBitMapMarker(startAddr, youngSize);
+#elif(defined SSE2) || (defined SSE3) || (defined SSE4)
+    checkObjectMap = new TSSE2BitMapMarker(startAddr, youngSize);
+#elif PROCESSOR_ARCH == X86
+    checkObjectMap = new TX86BitMapMarker(startAddr, youngSize);
+#elif PROCESSOR_ARCH == ARM
+
+#ifdef NEON
+    checkObjectMap = new TNeonBitMapMarker(startAddr, youngSize);
+#else
+    checkObjectMap = new TARMBitMapMarker(startAddr, youngSize);
+#endif
+
+#endif
+
   if (unlikely(!setupOverrideFunction(cms_new_hook))) {
     logger->printCritMsg("Cannot setup to override CMS_new (ParNew GC).");
     return false;
@@ -1269,6 +1293,7 @@
     /* Switch CMS hooking at new generation. */
     switchOverrideFunction(cms_new_hook, enable);
     list = cms_sweep_hook;
+    checkObjectMap->clear();
   } else if (vmVal->getUseG1()) {
     /* If users select G1, we prepare TSnapShotContainer NOW! */
     snapshotByGC = TSnapShotContainer::getInstance();
@@ -1507,6 +1532,11 @@
       return;
     }
 
+    if (checkObjectMap->checkAndMark(oop)) {
+      /* Object is in young gen and already marked. */
+      return;
+    }
+
     /* Invoke callback by CMS GC. */
     cmsCallbackFunc(oop, NULL);
   } else if (vmVal->getUseG1()) {
--- a/agent/src/heapstats-engines/vmFunctions.cpp	Thu Jun 02 22:23:18 2016 +0900
+++ b/agent/src/heapstats-engines/vmFunctions.cpp	Thu Jun 02 22:23:26 2016 +0900
@@ -33,7 +33,7 @@
 /*!
  * \brief Function pointer for "is_in_permanent".
  */
-THeap_IsInPermanent is_in_permanent = NULL;
+THeap_IsIn is_in_permanent = NULL;
 
 /* Internal function */
 
@@ -83,12 +83,12 @@
   /* Search "is_in_permanent" function symbol. */
   if (jvmInfo->isAfterCR6964458()) {
     /* Perm gen does not exist. */
-    is_in_permanent = (THeap_IsInPermanent)&dummyIsInPermanent;
+    is_in_permanent = (THeap_IsIn)&dummyIsInPermanent;
   } else if (vmVal->getUseParallel() || vmVal->getUseParOld()) {
-    is_in_permanent = (THeap_IsInPermanent) this->symFinder->findSymbol(
+    is_in_permanent = (THeap_IsIn) this->symFinder->findSymbol(
         IS_IN_PERM_ON_PARALLEL_GC_SYMBOL);
   } else {
-    is_in_permanent = (THeap_IsInPermanent) this->symFinder->findSymbol(
+    is_in_permanent = (THeap_IsIn) this->symFinder->findSymbol(
         IS_IN_PERM_ON_OTHER_GC_SYMBOL);
   }
 
@@ -97,6 +97,15 @@
     return false;
   }
 
+  /* Search "is_in" function symbol for ParNew GC when CMS GC is worked. */
+  if (vmVal->getUseCMS()) {
+    is_in = (THeap_IsIn) this->symFinder->findSymbol(IS_IN_SYMBOL);
+    if (unlikely(is_in == NULL)) {
+      logger->printCritMsg("is_in() not found.");
+      return false;
+    }
+  }
+
   /* Search "GetObjectSize" function symbol. */
   getObjectSize = (TJvmtiEnv_GetObjectSize) this->symFinder->findSymbol(
       SYMBOL_GETOBJCTSIZE);
--- a/agent/src/heapstats-engines/vmFunctions.hpp	Thu Jun 02 22:23:18 2016 +0900
+++ b/agent/src/heapstats-engines/vmFunctions.hpp	Thu Jun 02 22:23:26 2016 +0900
@@ -40,6 +40,11 @@
 #define IS_IN_PERM_ON_OTHER_GC_SYMBOL "_ZNK10SharedHeap15is_in_permanentEPKv"
 
 /*!
+ * \brief Symbol of Generation::is_in()
+ */
+#define IS_IN_SYMBOL "_ZNK10Generation5is_inEPKv"
+
+/*!
  * \brief Symbol of "JvmtiEnv::GetObjectSize" macro.
  */
 #ifdef __x86_64__
@@ -157,11 +162,11 @@
 /*!
  * \brief This function is C++ heap class member.<br>
  *        So 1st arg must be set instance.
- * \param thisptr [in] SharedHeap/ParallelScavengeHeap object instance.
+ * \param thisptr [in] Instance of Java memory region.
  * \param oop     [in] Java object.
- * \return Java object is existing in perm gen.
+ * \return true if oop is in this region.
  */
-typedef bool (*THeap_IsInPermanent)(void *thisptr, void *oop);
+typedef bool (*THeap_IsIn)(const void *thisptr, const void *oop);
 
 /*!
  * \brief This function is C++ JvmtiEnv class member.<br>
@@ -284,7 +289,7 @@
 
 /* extern variables */
 extern "C" void *VTableForTypeArrayOopClosure[2];
-extern "C" THeap_IsInPermanent is_in_permanent;
+extern "C" THeap_IsIn is_in_permanent;
 
 /*!
  * \brief This class gathers/provides functions in HotSpot VM.
@@ -297,6 +302,11 @@
   TJvmtiEnv_GetObjectSize getObjectSize;
 
   /*!
+   * \brief Function pointer for "Generation::is_in".
+   */
+  THeap_IsIn is_in;
+
+  /*!
    * \brief Function pointer for "java_lang_Class::as_klassOop".
    */
   TJavaLangClass_AsKlassOop asKlassOop;
@@ -418,6 +428,10 @@
     return getObjectSize(thisptr, object, size_ptr);
   }
 
+  inline bool IsInYoung(const void *oop) {
+    return is_in(TVMVariables::getInstance()->getYoungGen(), oop);
+  }
+
   inline void *AsKlassOop(void *mirror) { return asKlassOop(mirror); }
 
   inline void *GetClassLoaderForInstanceKlass(void *klassOop) {
--- a/agent/src/heapstats-engines/vmVariables.cpp	Thu Jun 02 22:23:18 2016 +0900
+++ b/agent/src/heapstats-engines/vmVariables.cpp	Thu Jun 02 22:23:26 2016 +0900
@@ -82,6 +82,9 @@
   ofsOSThreadThreadId = -1;
   ofsObjectMonitorObject = -1;
   threads_lock = NULL;
+  youngGen = NULL;
+  youngGenStartAddr = NULL;
+  youngGenSize = 0;
 
 #ifdef __LP64__
   HeapWordSize = 8;
@@ -366,6 +369,11 @@
   off_t offsetCmsShifter = -1;
   off_t offsetCmsMapAtCollector = -1;
   off_t offsetCmsVirtualSpace = -1;
+  off_t offsetGens = -1;
+  off_t offsetYoungGen = -1;
+  off_t offsetYoungGenReserved = -1;
+  off_t offsetMemRegionStart = -1;
+  off_t offsetMemRegionWordSize = -1;
   TOffsetNameMap ofsMap[] = {
       {"CMSBitMap", "_virtual_space", &offsetCmsVirtualSpace, NULL},
       {"CMSBitMap", "_bmStartWord", &offsetCmsStartWord, NULL},
@@ -373,6 +381,11 @@
       {"CMSCollector", "_markBitMap", &offsetCmsMapAtCollector, NULL},
       {"ConcurrentMarkSweepThread", "_collector", NULL, &cmsCollector},
       {"VirtualSpace", "_low", &offsetLowAtVirtualSpace, NULL},
+      {"GenCollectedHeap", "_gens", &offsetGens, NULL},
+      {"GenCollectedHeap", "_young_gen", &offsetYoungGen, NULL},
+      {"Generation", "_reserved", &offsetYoungGenReserved, NULL},
+      {"MemRegion", "_start", &offsetMemRegionStart, NULL},
+      {"MemRegion", "_word_size", &offsetMemRegionWordSize, NULL},
       /* End marker. */
       {NULL, NULL, NULL, NULL}};
 
@@ -401,6 +414,9 @@
   if (unlikely(offsetCmsVirtualSpace == -1 || offsetCmsStartWord == -1 ||
                offsetCmsShifter == -1 || offsetCmsMapAtCollector == -1 ||
                cmsCollector == NULL || offsetLowAtVirtualSpace == -1 ||
+               (offsetGens == -1 && offsetYoungGen == -1) ||
+               offsetYoungGenReserved == -1 || offsetMemRegionStart == -1 ||
+               offsetMemRegionWordSize == -1 ||
                *(void **)cmsCollector == NULL)) {
     logger->printCritMsg("Cannot get CMS values from VMStructs.");
     return false;
@@ -415,8 +431,19 @@
   ptrdiff_t virtSpace = cmsBitmapPtr + offsetCmsVirtualSpace;
   cmsBitMap_startAddr = *(size_t **)(virtSpace + offsetLowAtVirtualSpace);
 
+  youngGen = (offsetGens == -1) // JDK-8061802
+                ? *(void **)incAddress(collectedHeap, offsetYoungGen)
+                : *(void **)incAddress(collectedHeap, offsetGens);
+  void *youngGenReserved = incAddress(youngGen, offsetYoungGenReserved);
+  youngGenStartAddr =
+               *(void **)incAddress(youngGenReserved, offsetMemRegionStart);
+  size_t youngGenWordSize =
+               *(size_t *)incAddress(youngGenReserved, offsetMemRegionWordSize);
+  youngGenSize = youngGenWordSize * HeapWordSize;
+
   if (unlikely((cmsBitMap_startWord == NULL) ||
-               (cmsBitMap_startAddr == NULL))) {
+               (cmsBitMap_startAddr == NULL) ||
+               (youngGen == NULL) || (youngGenStartAddr == NULL))) {
     logger->printCritMsg("Cannot calculate CMS values.");
     return false;
   }
--- a/agent/src/heapstats-engines/vmVariables.hpp	Thu Jun 02 22:23:18 2016 +0900
+++ b/agent/src/heapstats-engines/vmVariables.hpp	Thu Jun 02 22:23:26 2016 +0900
@@ -312,6 +312,21 @@
    */
   void *threads_lock;
 
+  /*!
+   * \brief Pointer of YoungGen in GenCollectedHeap.
+   */
+  void *youngGen;
+
+  /*!
+   * \brief Start address of YoungGen.
+   */
+  void *youngGenStartAddr;
+
+  /*!
+   * \brief sizeof YoungGen.
+   */
+  size_t youngGenSize;
+
   /* Class of HeapStats for scanning variables in HotSpot VM */
   TSymbolFinder *symFinder;
   TVMStructScanner *vmScanner;
@@ -447,6 +462,9 @@
   inline off_t getOfsOSThreadThreadId() { return ofsOSThreadThreadId; };
   inline off_t getOfsObjectMonitorObject() { return ofsObjectMonitorObject; };
   inline void *getThreadsLock() { return threads_lock; };
+  inline void *getYoungGen() const { return youngGen; };
+  inline void *getYoungGenStartAddr() const { return youngGenStartAddr; };
+  inline size_t getYoungGenSize() const { return youngGenSize; };
 };
 
 #endif  // VMVARIABLES_H