]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
CastleProto: track next top explicitly
authorJustin Viiret <justin.viiret@intel.com>
Wed, 2 Dec 2015 22:27:57 +0000 (09:27 +1100)
committerMatthew Barr <matthew.barr@intel.com>
Sun, 6 Dec 2015 22:38:32 +0000 (09:38 +1100)
Repeats may be removed (e.g. by pruning in role aliasing passes)
leaving "holes" in the top map. Track the next top to use explicitly,
rather than using repeats.size().

src/nfa/castlecompile.cpp
src/nfa/castlecompile.h
src/rose/rose_build_role_aliasing.cpp

index 8d7f3913a4cd20a5527e18b7528235adb0d6b756..cc5c599b274097994435a1765026d76e756729bf 100644 (file)
@@ -740,19 +740,13 @@ const CharReach &CastleProto::reach() const {
     return repeats.begin()->second.reach;
 }
 
-static
-u32 find_next_top(const map<u32, PureRepeat> &repeats) {
-    u32 top = verify_u32(repeats.size());
-    assert(!contains(repeats, top));
-    return top;
-}
-
 u32 CastleProto::add(const PureRepeat &pr) {
     assert(repeats.size() < max_occupancy);
     assert(pr.reach == reach());
     assert(pr.reports.size() == 1);
-    u32 top = find_next_top(repeats);
+    u32 top = next_top++;
     DEBUG_PRINTF("selected unused top %u\n", top);
+    assert(!contains(repeats, top));
     repeats.emplace(top, pr);
     for (const auto &report : pr.reports) {
         report_map[report].insert(top);
@@ -760,6 +754,15 @@ u32 CastleProto::add(const PureRepeat &pr) {
     return top;
 }
 
+void CastleProto::erase(u32 top) {
+    DEBUG_PRINTF("erase top %u\n", top);
+    assert(contains(repeats, top));
+    repeats.erase(top);
+    for (auto &m : report_map) {
+        m.second.erase(top);
+    }
+}
+
 u32 CastleProto::merge(const PureRepeat &pr) {
     assert(repeats.size() <= max_occupancy);
     assert(pr.reach == reach());
@@ -820,7 +823,7 @@ void remapCastleTops(CastleProto &proto, map<u32, u32> &top_map) {
     for (const auto &m : proto.repeats) {
         const u32 top = m.first;
         const PureRepeat &pr = m.second;
-        u32 new_top = find_next_top(out);
+        u32 new_top = out.size();
         out.emplace(new_top, pr);
         top_map[top] = new_top;
     }
index 8ca3581c60d573428ed7fb049b29aa780626cc71..fc4bb9913042c4379bd95cbc965d7d17bdf1670b 100644 (file)
@@ -68,8 +68,12 @@ struct CastleProto {
     explicit CastleProto(const PureRepeat &pr);
     const CharReach &reach() const;
 
+    /** \brief Add a new repeat. */
     u32 add(const PureRepeat &pr);
 
+    /** \brief Remove a repeat. */
+    void erase(u32 top);
+
     /**
      * \brief Merge in the given repeat, returning the top used.
      *
@@ -84,6 +88,12 @@ struct CastleProto {
 
     /** \brief Mapping from report to associated tops. */
     ue2::unordered_map<ReportID, flat_set<u32>> report_map;
+
+    /**
+     * \brief Next top id to use. Repeats may be removed without top remapping,
+     * so we track this explicitly instead of using repeats.size().
+     */
+    u32 next_top = 1;
 };
 
 std::set<ReportID> all_reports(const CastleProto &proto);
index 62db5b2eaf469368dd6d92408e2437da5102d0dd..88deaa257263d6f831bcb04a836d88560aaf1f89 100644 (file)
@@ -751,14 +751,17 @@ void pruneReportIfUnused(const RoseBuildImpl &tbi, shared_ptr<NGHolder> h,
  * Castle. */
 static
 void pruneCastle(CastleProto &castle, ReportID report) {
-    for (map<u32, PureRepeat>::iterator it = castle.repeats.begin();
-         it != castle.repeats.end(); /* incr inside */) {
-        if (contains(it->second.reports, report)) {
-            ++it;
-        } else {
-            castle.repeats.erase(it++);
+    unordered_set<u32> dead; // tops to remove.
+    for (const auto &m : castle.repeats) {
+        if (!contains(m.second.reports, report)) {
+            dead.insert(m.first);
         }
     }
+
+    for (const auto &top : dead) {
+        castle.erase(top);
+    }
+
     assert(!castle.repeats.empty());
 }
 
@@ -798,7 +801,7 @@ void pruneUnusedTops(CastleProto &castle, const RoseGraph &g,
     for (u32 top : assoc_keys(castle.repeats)) {
         if (!contains(used_tops, top)) {
             DEBUG_PRINTF("removing unused top %u\n", top);
-            castle.repeats.erase(top);
+            castle.erase(top);
         }
     }
 }