[libFuzzer] refactor the handling of instrumentation counters so that they are grouped in regions one full page each. Needed for future optimization. NFC

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer@352603 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/FuzzerTracePC.h b/FuzzerTracePC.h
index 505b827..2ab75b8 100644
--- a/FuzzerTracePC.h
+++ b/FuzzerTracePC.h
@@ -125,10 +125,38 @@
   bool DoPrintNewPCs = false;
   size_t NumPrintNewFuncs = 0;
 
-  struct { uint8_t *Start, *Stop; } ModuleCounters[4096];
-  size_t NumModulesWithInline8bitCounters;  // linker-initialized.
+  // Module represents the array of 8-bit counters split into regions
+  // such that every region, except maybe the first and the last one, is one
+  // full page.
+  struct Module {
+    struct Region {
+      uint8_t *Start, *Stop;
+      bool Enabled;
+      bool OneFullPage;
+    };
+    Region *Regions;
+    size_t NumRegions;
+    uint8_t *Start() { return Regions[0].Start; }
+    uint8_t *Stop()  { return Regions[NumRegions - 1].Stop; }
+    size_t Size()   { return Stop() - Start(); }
+    size_t  Idx(uint8_t *P) {
+      assert(P >= Start() && P < Stop());
+      return P - Start();
+    }
+  };
+
+  Module Modules[4096];
+  size_t NumModules;  // linker-initialized.
   size_t NumInline8bitCounters;
 
+  template <class Callback>
+  void IterateCounterRegions(Callback CB) {
+    for (size_t m = 0; m < NumModules; m++)
+      for (size_t r = 0; r < Modules[m].NumRegions; r++)
+        CB(Modules[m].Regions[r]);
+  }
+
+
   struct PCTableEntry {
     uintptr_t PC, PCFlags;
   };
@@ -140,7 +168,7 @@
   Set<uintptr_t> ObservedPCs;
   std::unordered_map<uintptr_t, uintptr_t> ObservedFuncs;  // PC => Counter.
 
-  std::pair<size_t, size_t> FocusFunction = {-1, -1};  // Module and PC IDs.
+  uint8_t *FocusFunctionCounterPtr = nullptr;
 
   ValueBitMap ValueProfileMap;
   uintptr_t InitialStack;
@@ -149,7 +177,7 @@
 template <class Callback>
 // void Callback(size_t FirstFeature, size_t Idx, uint8_t Value);
 ATTRIBUTE_NO_SANITIZE_ALL
-void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
+size_t ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
                         size_t FirstFeature, Callback Handle8bitCounter) {
   typedef uintptr_t LargeType;
   const size_t Step = sizeof(LargeType) / sizeof(uint8_t);
@@ -171,6 +199,7 @@
   for (; P < End; P++)
     if (uint8_t V = *P)
       Handle8bitCounter(FirstFeature, P - Begin, V);
+  return End - Begin;
 }
 
 // Given a non-zero Counter returns a number in the range [0,7].
@@ -213,17 +242,18 @@
 
   size_t FirstFeature = 0;
 
-  if (NumInline8bitCounters) {
-    for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
-      ForEachNonZeroByte(ModuleCounters[i].Start, ModuleCounters[i].Stop,
-                         FirstFeature, Handle8bitCounter);
-      FirstFeature += 8 * (ModuleCounters[i].Stop - ModuleCounters[i].Start);
+  for (size_t i = 0; i < NumModules; i++) {
+    for (size_t r = 0; r < Modules[i].NumRegions; r++) {
+      if (!Modules[i].Regions[r].Enabled) continue;
+      FirstFeature += 8 * ForEachNonZeroByte(Modules[i].Regions[r].Start,
+                                             Modules[i].Regions[r].Stop,
+                                             FirstFeature, Handle8bitCounter);
     }
   }
 
-  ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
-                     Handle8bitCounter);
-  FirstFeature += (ExtraCountersEnd() - ExtraCountersBegin()) * 8;
+  FirstFeature +=
+      8 * ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(),
+                             FirstFeature, Handle8bitCounter);
 
   if (UseValueProfileMask) {
     ValueProfileMap.ForEach([&](size_t Idx) {