]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
rose: replace RoseLiteralMap use of bimap
authorJustin Viiret <justin.viiret@intel.com>
Wed, 26 Apr 2017 05:12:27 +0000 (15:12 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Tue, 30 May 2017 03:58:59 +0000 (13:58 +1000)
This apoproach is simpler and more efficient for cases with large
numbers of literals.

15 files changed:
src/rose/rose_build_add.cpp
src/rose/rose_build_bytecode.cpp
src/rose/rose_build_castle.cpp
src/rose/rose_build_compile.cpp
src/rose/rose_build_convert.cpp
src/rose/rose_build_dedupe.cpp
src/rose/rose_build_dump.cpp
src/rose/rose_build_groups.cpp
src/rose/rose_build_impl.h
src/rose/rose_build_lookaround.cpp
src/rose/rose_build_matchers.cpp
src/rose/rose_build_merge.cpp
src/rose/rose_build_misc.cpp
src/rose/rose_build_program.cpp
src/rose/rose_build_role_aliasing.cpp

index b53f7c8ac06cee267ee7079d5195f3335e2738af..26f884457b1a7429067d5fff74522c816cd34f48 100644 (file)
@@ -295,7 +295,7 @@ void createVertices(RoseBuildImpl *tbi,
             if (bd.som && !g[w].left.haig) {
                 /* no prefix - som based on literal start */
                 assert(!prefix_graph);
-                g[w].som_adjust = tbi->literals.right.at(literalId).elength();
+                g[w].som_adjust = tbi->literals.at(literalId).elength();
                 DEBUG_PRINTF("set som_adjust to %u\n", g[w].som_adjust);
             }
 
@@ -333,7 +333,7 @@ void createVertices(RoseBuildImpl *tbi,
         u32 ghostId = tbi->literal_info[literalId].undelayed_id;
         DEBUG_PRINTF("creating delay ghost vertex, id=%u\n", ghostId);
         assert(ghostId != literalId);
-        assert(tbi->literals.right.at(ghostId).delay == 0);
+        assert(tbi->literals.at(ghostId).delay == 0);
 
         // Adjust offsets, removing delay.
         u32 ghost_min = min_offset, ghost_max = max_offset;
@@ -1907,16 +1907,20 @@ void removeAddedLiterals(RoseBuildImpl &tbi, const flat_set<u32> &lit_ids) {
         return;
     }
 
+    DEBUG_PRINTF("remove last %zu literals\n", lit_ids.size());
+
     // lit_ids should be a contiguous range.
     assert(lit_ids.size() == *lit_ids.rbegin() - *lit_ids.begin() + 1);
+    assert(*lit_ids.rbegin() == tbi.literals.size() - 1);
 
-    for (const u32 &lit_id : lit_ids) {
-        assert(lit_id < tbi.literal_info.size());
-        assert(tbi.literals.right.at(lit_id).table == ROSE_ANCHORED);
-        assert(tbi.literal_info[lit_id].vertices.empty());
+    assert(all_of_in(lit_ids, [&](u32 lit_id) {
+        return lit_id < tbi.literal_info.size() &&
+               tbi.literals.at(lit_id).table == ROSE_ANCHORED &&
+               tbi.literal_info[lit_id].vertices.empty();
+    }));
 
-        tbi.literals.right.erase(lit_id);
-    }
+    tbi.literals.erase_back(lit_ids.size());
+    assert(tbi.literals.size() == *lit_ids.begin());
 
     // lit_ids should be at the end of tbi.literal_info.
     assert(tbi.literal_info.size() == *lit_ids.rbegin() + 1);
index 636af0a6a47225fd331f8a020fd8a51f3c6da388..dfe4ff635ca0cd957b94c20e01ffa26d58981650 100644 (file)
@@ -746,8 +746,8 @@ void findTriggerSequences(const RoseBuildImpl &tbi,
         const u32 top = e.first;
         const set<u32> &lit_ids = e.second;
 
-        for (u32 id :  lit_ids) {
-            const rose_literal_id &lit = tbi.literals.right.at(id);
+        for (u32 id : lit_ids) {
+            const rose_literal_id &lit = tbi.literals.at(id);
             (*trigger_lits)[top].push_back(as_cr_seq(lit));
         }
     }
@@ -905,8 +905,8 @@ u32 decreaseLag(const RoseBuildImpl &build, NGHolder &h,
     for (RoseVertex v : succs) {
         u32 lag = rg[v].left.lag;
         for (u32 lit_id : rg[v].literals) {
-            u32 delay = build.literals.right.at(lit_id).delay;
-            const ue2_literal &literal = build.literals.right.at(lit_id).s;
+            u32 delay = build.literals.at(lit_id).delay;
+            const ue2_literal &literal = build.literals.at(lit_id).s;
             assert(lag <= literal.length() + delay);
             size_t base = literal.length() + delay - lag;
             if (base >= literal.length()) {
@@ -1134,7 +1134,7 @@ bool buildLeftfix(RoseBuildImpl &build, build_context &bc, bool prefix, u32 qi,
         for (RoseVertex v : succs) {
             for (auto u : inv_adjacent_vertices_range(v, g)) {
                 for (u32 lit_id : g[u].literals) {
-                    lits.insert(build.literals.right.at(lit_id).s);
+                    lits.insert(build.literals.at(lit_id).s);
                 }
             }
         }
@@ -1315,7 +1315,7 @@ void updateExclusiveInfixProperties(const RoseBuildImpl &build,
                 set<ue2_literal> lits;
                 for (auto u : inv_adjacent_vertices_range(v, build.g)) {
                     for (u32 lit_id : build.g[u].literals) {
-                        lits.insert(build.literals.right.at(lit_id).s);
+                        lits.insert(build.literals.at(lit_id).s);
                     }
                 }
                 DEBUG_PRINTF("%zu literals\n", lits.size());
@@ -2117,9 +2117,8 @@ u32 RoseBuildImpl::calcHistoryRequired() const {
     }
 
     // Delayed literals contribute to history requirement as well.
-    for (const auto &e : literals.right) {
-        const u32 id = e.first;
-        const auto &lit = e.second;
+    for (u32 id = 0; id < literals.size(); id++) {
+        const auto &lit = literals.at(id);
         if (lit.delay) {
             // If the literal is delayed _and_ has a mask that is longer than
             // the literal, we need enough history to match the whole mask as
@@ -2716,11 +2715,11 @@ void buildLeftInfoTable(const RoseBuildImpl &tbi, build_context &bc,
             } else {
                 left.lagIndex = ROSE_OFFSET_INVALID;
             }
-
-            DEBUG_PRINTF("rose %u is %s\n", left_index,
-                         left.infix ? "infix" : "prefix");
         }
 
+        DEBUG_PRINTF("rose %u is %s\n", left_index,
+                     left.infix ? "infix" : "prefix");
+
         // Update squash mask.
         left.squash_mask &= lbi.squash_mask;
 
@@ -2853,9 +2852,8 @@ vector<LitFragment> groupByFragment(const RoseBuildImpl &build) {
 
     map<rose_literal_id, FragmentInfo> frag_info;
 
-    for (const auto &m : build.literals.right) {
-        const u32 lit_id = m.first;
-        const auto &lit = m.second;
+    for (u32 lit_id = 0; lit_id < build.literals.size(); lit_id++) {
+        const auto &lit = build.literals.at(lit_id);
         const auto &info = build.literal_info.at(lit_id);
 
         if (!isUsedLiteral(build, lit_id)) {
@@ -2993,7 +2991,7 @@ pair<u32, u32> writeAnchoredPrograms(const RoseBuildImpl &build,
 
     for (const auto &frag : fragments) {
         for (const u32 lit_id : frag.lit_ids) {
-            const auto &lit = build.literals.right.at(lit_id);
+            const auto &lit = build.literals.at(lit_id);
 
             if (lit.table != ROSE_ANCHORED) {
                 continue;
@@ -3238,7 +3236,7 @@ void fillMatcherDistances(const RoseBuildImpl &build, RoseEngine *engine) {
         assert(g[v].min_offset <= g[v].max_offset);
 
         for (u32 lit_id : g[v].literals) {
-            const rose_literal_id &key = build.literals.right.at(lit_id);
+            const rose_literal_id &key = build.literals.at(lit_id);
             u32 max_d = g[v].max_offset;
             u32 min_d = g[v].min_offset;
 
@@ -3371,9 +3369,8 @@ pair<size_t, size_t> floatingCountAndMaxLen(const RoseBuildImpl &build) {
     size_t num = 0;
     size_t max_len = 0;
 
-    for (const auto &e : build.literals.right) {
-        const u32 id = e.first;
-        const rose_literal_id &lit = e.second;
+    for (u32 id = 0; id < build.literals.size(); id++) {
+        const rose_literal_id &lit = build.literals.at(id);
 
         if (lit.table != ROSE_FLOATING) {
             continue;
index 7987b0f6138e79c89afbeed263f7e8d8d65634a6..a85a784fc1e0c0c747393e84d8094254eec67cb8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016, Intel Corporation
+ * Copyright (c) 2015-2017, Intel Corporation
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -131,7 +131,7 @@ vector<rose_literal_id> literals_for_vertex(const RoseBuildImpl &tbi,
     vector<rose_literal_id> rv;
 
     for (const u32 id : tbi.g[v].literals) {
-        rv.push_back(tbi.literals.right.at(id));
+        rv.push_back(tbi.literals.at(id));
     }
 
     return rv;
@@ -366,7 +366,7 @@ bool triggerKillsRoseCastle(const RoseBuildImpl &tbi, const left_id &left,
     /* check each pred literal to see if they all kill previous castle
      * state */
     for (u32 lit_id : tbi.g[source(e, tbi.g)].literals) {
-        const rose_literal_id &pred_lit = tbi.literals.right.at(lit_id);
+        const rose_literal_id &pred_lit = tbi.literals.at(lit_id);
         const ue2_literal s = findNonOverlappingTail(all_lits, pred_lit.s);
         const CharReach &cr = c.reach();
 
index f4c2613eca6aa70f40069300f0f868c78f2d432b..96241e39d1a747d929948168138182924d4c4d39 100644 (file)
@@ -119,7 +119,7 @@ void removeLiteralFromGraph(RoseBuildImpl &build, u32 id) {
  */
 static
 void explodeLiteral(RoseBuildImpl &build, u32 id) {
-    const auto &lit = build.literals.right.at(id);
+    const auto &lit = build.literals.at(id);
     auto &info = build.literal_info[id];
 
     assert(!info.group_mask); // not set yet
@@ -139,7 +139,7 @@ void explodeLiteral(RoseBuildImpl &build, u32 id) {
         DEBUG_PRINTF("adding exploded lit %u: '%s'\n", new_id,
                      dumpString(new_str).c_str());
 
-        const auto &new_lit = build.literals.right.at(new_id);
+        const auto &new_lit = build.literals.at(new_id);
         auto &new_info = build.literal_info.at(new_id);
         insert(&new_info.vertices, info.vertices);
         for (const auto &v : info.vertices) {
@@ -150,7 +150,7 @@ void explodeLiteral(RoseBuildImpl &build, u32 id) {
         if (!info.delayed_ids.empty()) {
             flat_set<u32> &del_ids = new_info.delayed_ids;
             for (u32 delay_id : info.delayed_ids) {
-                const auto &dlit = build.literals.right.at(delay_id);
+                const auto &dlit = build.literals.at(delay_id);
                 u32 new_delay_id =
                     build.getLiteralId(new_lit.s, new_lit.msk, new_lit.cmp,
                                        dlit.delay, dlit.table);
@@ -170,9 +170,8 @@ void explodeLiteral(RoseBuildImpl &build, u32 id) {
 
 void RoseBuildImpl::handleMixedSensitivity(void) {
     vector<u32> explode;
-    for (const auto &e : literals.right) {
-        u32 id = e.first;
-        const rose_literal_id &lit = e.second;
+    for (u32 id = 0; id < literals.size(); id++) {
+        const rose_literal_id &lit = literals.at(id);
 
         if (lit.delay) {
             continue; /* delay id's are virtual-ish */
@@ -420,7 +419,7 @@ bool RoseBuildImpl::isDirectReport(u32 id) const {
             }
         }
 
-        if (literals.right.at(id).table == ROSE_ANCHORED) {
+        if (literals.at(id).table == ROSE_ANCHORED) {
             /* in-edges are irrelevant for anchored region. */
             continue;
         }
@@ -439,7 +438,7 @@ bool RoseBuildImpl::isDirectReport(u32 id) const {
     }
 
     DEBUG_PRINTF("literal %u ('%s') is a %s report\n", id,
-                 dumpString(literals.right.at(id).s).c_str(),
+                 dumpString(literals.at(id).s).c_str(),
                  info.vertices.size() > 1 ? "multi-direct" : "direct");
     return true;
 }
@@ -511,8 +510,7 @@ bool checkEodStealFloating(const RoseBuildImpl &build,
 
     // Collect a set of all floating literals.
     unordered_set<ue2_literal> floating_lits;
-    for (auto &m : build.literals) {
-        const auto &lit = m.left;
+    for (auto &lit : build.literals) {
         if (lit.table == ROSE_FLOATING) {
             floating_lits.insert(lit.s);
         }
@@ -524,7 +522,7 @@ bool checkEodStealFloating(const RoseBuildImpl &build,
     u32 new_floating_lits = 0;
 
     for (u32 eod_id : eodLiteralsForFloating) {
-        const rose_literal_id &lit = build.literals.right.at(eod_id);
+        const rose_literal_id &lit = build.literals.at(eod_id);
         DEBUG_PRINTF("checking '%s'\n", dumpString(lit.s).c_str());
 
         if (contains(floating_lits, lit.s)) {
@@ -558,12 +556,16 @@ bool checkEodStealFloating(const RoseBuildImpl &build,
 
 static
 void promoteEodToFloating(RoseBuildImpl &tbi, const vector<u32> &eodLiterals) {
-    DEBUG_PRINTF("promoting eod literals to floating table\n");
+    DEBUG_PRINTF("promoting %zu eod literals to floating table\n",
+                 eodLiterals.size());
 
     for (u32 eod_id : eodLiterals) {
-        const rose_literal_id &lit = tbi.literals.right.at(eod_id);
+        const rose_literal_id &lit = tbi.literals.at(eod_id);
+        DEBUG_PRINTF("eod_id=%u, lit=%s\n", eod_id, dumpString(lit.s).c_str());
         u32 floating_id = tbi.getLiteralId(lit.s, lit.msk, lit.cmp, lit.delay,
                                            ROSE_FLOATING);
+        DEBUG_PRINTF("floating_id=%u, lit=%s\n", floating_id,
+                     dumpString(tbi.literals.at(floating_id).s).c_str());
         auto &float_verts = tbi.literal_info[floating_id].vertices;
         auto &eod_verts = tbi.literal_info[eod_id].vertices;
 
@@ -588,7 +590,7 @@ bool promoteEodToAnchored(RoseBuildImpl &tbi, const vector<u32> &eodLiterals) {
     bool rv = true;
 
     for (u32 eod_id : eodLiterals) {
-        const rose_literal_id &lit = tbi.literals.right.at(eod_id);
+        const rose_literal_id &lit = tbi.literals.at(eod_id);
 
         NGHolder h;
         add_edge(h.start, h.accept, h);
@@ -728,7 +730,7 @@ void stealEodVertices(RoseBuildImpl &tbi) {
             continue; // skip unused literals
         }
 
-        const rose_literal_id &lit = tbi.literals.right.at(i);
+        const rose_literal_id &lit = tbi.literals.at(i);
 
         if (lit.table == ROSE_EOD_ANCHORED) {
             if (suitableForAnchored(tbi, lit, info)) {
@@ -770,7 +772,7 @@ bool RoseBuildImpl::isDelayed(u32 id) const {
 
 bool RoseBuildImpl::hasDelayedLiteral(RoseVertex v) const {
     for (u32 lit_id : g[v].literals) {
-        if (literals.right.at(lit_id).delay) {
+        if (literals.at(lit_id).delay) {
             return true;
         }
     }
@@ -1096,7 +1098,7 @@ bool triggerKillsRoseGraph(const RoseBuildImpl &build, const left_id &left,
     /* check each pred literal to see if they all kill previous graph
      * state */
     for (u32 lit_id : build.g[source(e, build.g)].literals) {
-        const rose_literal_id &pred_lit = build.literals.right.at(lit_id);
+        const rose_literal_id &pred_lit = build.literals.at(lit_id);
         const ue2_literal s = findNonOverlappingTail(all_lits, pred_lit.s);
 
         DEBUG_PRINTF("running graph %zu\n", states.size());
@@ -1170,7 +1172,7 @@ void findTopTriggerCancels(RoseBuildImpl &build) {
         }
 
         for (u32 lit_id : pred_lit_ids) {
-            const rose_literal_id &p_lit = build.literals.right.at(lit_id);
+            const rose_literal_id &p_lit = build.literals.at(lit_id);
             if (p_lit.delay || p_lit.table == ROSE_ANCHORED) {
                 goto next_rose;
             }
@@ -1271,7 +1273,7 @@ void countFloatingLiterals(const RoseBuildImpl &tbi, u32 *total_count,
                            u32 *short_count) {
     *total_count = 0;
     *short_count = 0;
-    for (const rose_literal_id &lit : tbi.literals.right | map_values) {
+    for (const rose_literal_id &lit : tbi.literals) {
         if (lit.delay) {
             continue; /* delay id's are virtual-ish */
         }
index 89eac225acf54fe21534f80776631fdafcbe971c..0c1f433863da5f26cf1656e1d87d4282166fc0e3 100644 (file)
@@ -235,7 +235,7 @@ void convertFloodProneSuffix(RoseBuildImpl &tbi, RoseVertex v, u32 lit_id,
 static
 size_t findFloodProneSuffixLen(const RoseBuildImpl &tbi) {
     size_t numLiterals = 0;
-    for (const rose_literal_id &lit : tbi.literals.right | map_values) {
+    for (const rose_literal_id &lit : tbi.literals) {
         if (lit.delay) {
             continue; // delay ids are virtual-ish
         }
@@ -293,7 +293,7 @@ void convertFloodProneSuffixes(RoseBuildImpl &tbi) {
         }
 
         u32 lit_id = *g[v].literals.begin();
-        const rose_literal_id &lit = tbi.literals.right.at(lit_id);
+        const rose_literal_id &lit = tbi.literals.at(lit_id);
 
         // anchored or delayed literals need thought.
         if (lit.table != ROSE_FLOATING || lit.delay) {
index dbff7aa7e1a7b455c40820e84494a3b28a5cd9e1..d3e72313342fdc09501abd931fd007fe4fd29916 100644 (file)
@@ -311,9 +311,9 @@ bool RoseDedupeAuxImpl::requiresDedupeSupport(
     }
 
     for (auto it = begin(lits); it != end(lits); ++it) {
-        const auto &lit1 = build.literals.right.at(it->first);
+        const auto &lit1 = build.literals.at(it->first);
         for (auto jt = next(it); jt != end(lits); ++jt) {
-            const auto &lit2 = build.literals.right.at(jt->first);
+            const auto &lit2 = build.literals.at(jt->first);
             if (literalsCouldRace(lit1, lit2)) {
                 DEBUG_PRINTF("literals could race\n");
                 return true;
index dfbbe1162dfd72d3768c07063a1282637f8e61fa..7fd19d43684eb75e90975e88b329f2f6020af0b6 100644 (file)
@@ -257,17 +257,13 @@ private:
             os << "/nofrag ";
         }
 
-        if (contains(build.literals.right, id)) {
-            const auto &lit = build.literals.right.at(id);
-            os << '\'' << dotEscapeString(lit.s.get_string()) << '\'';
-            if (lit.s.any_nocase()) {
-                os << " (nocase)";
-            }
-            if (lit.delay) {
-                os << " +" << lit.delay;
-            }
-        } else {
-            os << "<unknown>";
+        const auto &lit = build.literals.at(id);
+        os << '\'' << dotEscapeString(lit.s.get_string()) << '\'';
+        if (lit.s.any_nocase()) {
+            os << " (nocase)";
+        }
+        if (lit.delay) {
+            os << " +" << lit.delay;
         }
     }
 
@@ -358,15 +354,16 @@ void dumpRoseLiterals(const RoseBuildImpl &build,
     DEBUG_PRINTF("dumping literals\n");
     ofstream os(grey.dumpPath + "rose_literals.txt");
 
-    os << "ROSE LITERALS: a total of " << build.literals.right.size()
-       << " literals and " << num_vertices(g) << " roles." << endl << endl;
+    os << "ROSE LITERALS: a total of " << build.literals.size()
+       << " literals and " << num_vertices(g) << " roles." << endl
+       << endl;
 
-    for (const auto &e : build.literals.right) {
-        u32 id = e.first;
-        const ue2_literal &s = e.second.s;
+    for (u32 id = 0; id < build.literals.size(); id++) {
+        const auto &lit = build.literals.at(id);
+        const ue2_literal &s = lit.s;
         const rose_literal_info &lit_info = build.literal_info[id];
 
-        switch (e.second.table) {
+        switch (lit.table) {
         case ROSE_ANCHORED:
             os << "ANCHORED";
             break;
@@ -397,8 +394,8 @@ void dumpRoseLiterals(const RoseBuildImpl &build,
             os << " benefits,";
         }
 
-        if (e.second.delay) {
-            os << " delayed "<< e.second.delay << ",";
+        if (lit.delay) {
+            os << " delayed "<< lit.delay << ",";
         }
 
         os << " groups 0x" << hex << setw(16) << setfill('0')
index f17e1ee4a97fc5794df529f1b0dc7b798b39a5e8..c670e60334125919a0c84564b561c58da816f2e4 100644 (file)
@@ -238,9 +238,8 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
     u32 group_always_on = 0;
 
     // First pass: handle always on literals.
-    for (const auto &e : literals.right) {
-        u32 id = e.first;
-        const rose_literal_id &lit = e.second;
+    for (u32 id = 0; id < literals.size(); id++) {
+        const rose_literal_id &lit = literals.at(id);
         rose_literal_info &info = literal_info[id];
 
         if (!requires_group_assignment(lit, info)) {
@@ -274,9 +273,8 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
     priority_queue<tuple<s32, s32, u32>> pq;
 
     // Second pass: the other literals.
-    for (const auto &e : literals.right) {
-        u32 id = e.first;
-        const rose_literal_id &lit = e.second;
+    for (u32 id = 0; id < literals.size(); id++) {
+        const rose_literal_id &lit = literals.at(id);
         rose_literal_info &info = literal_info[id];
 
         if (!requires_group_assignment(lit, info)) {
@@ -290,7 +288,7 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
     while (!pq.empty()) {
         u32 id = get<2>(pq.top());
         pq.pop();
-        UNUSED const rose_literal_id &lit = literals.right.at(id);
+        UNUSED const rose_literal_id &lit = literals.at(id);
         DEBUG_PRINTF("assigning groups to lit %u (v %zu l %zu)\n", id,
                      literal_info[id].vertices.size(), lit.s.length());
 
@@ -361,9 +359,8 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
         }
     }
     /* assign delayed literals to the same group as their parent */
-    for (const auto &e : literals.right) {
-        u32 id = e.first;
-        const rose_literal_id &lit = e.second;
+    for (u32 id = 0; id < literals.size(); id++) {
+        const rose_literal_id &lit = literals.at(id);
 
         if (!lit.delay) {
             continue;
@@ -378,7 +375,7 @@ void assignGroupsToLiterals(RoseBuildImpl &build) {
     }
 
     DEBUG_PRINTF("populate group to literal mapping\n");
-    for (const u32 id : literals.right | map_keys) {
+    for (u32 id = 0; id < literals.size(); id++) {
         rose_group groups = literal_info[id].group_mask;
         while (groups) {
             u32 group_id = findAndClearLSB_64(&groups);
@@ -561,10 +558,10 @@ bool isGroupSquasher(const RoseBuildImpl &build, const u32 id /* literal id */,
     const rose_literal_info &lit_info = build.literal_info.at(id);
 
     DEBUG_PRINTF("checking if %u '%s' is a group squasher %016llx\n", id,
-                  dumpString(build.literals.right.at(id).s).c_str(),
-                  lit_info.group_mask);
+                 dumpString(build.literals.at(id).s).c_str(),
+                 lit_info.group_mask);
 
-    if (build.literals.right.at(id).table == ROSE_EVENT) {
+    if (build.literals.at(id).table == ROSE_EVENT) {
         DEBUG_PRINTF("event literal\n");
         return false;
     }
@@ -693,9 +690,10 @@ bool isGroupSquasher(const RoseBuildImpl &build, const u32 id /* literal id */,
 
 void findGroupSquashers(RoseBuildImpl &build) {
     rose_group forbidden_squash_group = build.boundary_group_mask;
-    for (const auto &e : build.literals.right) {
-        if (e.second.delay) {
-            forbidden_squash_group |= build.literal_info[e.first].group_mask;
+    for (u32 id = 0; id < build.literals.size(); id++) {
+        const auto &lit = build.literals.at(id);
+        if (lit.delay) {
+            forbidden_squash_group |= build.literal_info[id].group_mask;
         }
     }
 
index f4916604a8b9b3dc0b498194b5933cb720c01458..13f1cfc9c655895f10aaa459cb6fca5857dc7f66 100644 (file)
 #include "nfagraph/ng_holder.h"
 #include "nfagraph/ng_revacc.h"
 #include "util/bytecode_ptr.h"
+#include "util/hash.h"
 #include "util/order_check.h"
 #include "util/queue_index_factory.h"
 #include "util/ue2_containers.h"
+#include "util/ue2string.h"
+#include "util/verify_types.h"
 
 #include <deque>
 #include <map>
 #include <string>
 #include <vector>
-#include <boost/bimap.hpp>
-#include <boost/functional/hash/hash.hpp>
 #include <boost/variant.hpp>
 
 struct RoseEngine;
@@ -300,6 +301,11 @@ struct rose_literal_id {
         }
         return MAX(mask_len, s.length()) + delay;
     }
+
+    bool operator==(const rose_literal_id &b) const {
+        return s == b.s && msk == b.msk && cmp == b.cmp && table == b.table &&
+               delay == b.delay && distinctiveness == b.distinctiveness;
+    }
 };
 
 static inline
@@ -313,8 +319,60 @@ bool operator<(const rose_literal_id &a, const rose_literal_id &b) {
     return 0;
 }
 
-// Literals are stored in a map from (string, nocase) -> ID
-typedef boost::bimap<rose_literal_id, u32> RoseLiteralMap;
+inline
+size_t hash_value(const rose_literal_id &lit) {
+    return hash_all(lit.s, lit.msk, lit.cmp, lit.table, lit.delay,
+                    lit.distinctiveness);
+}
+
+class RoseLiteralMap {
+    /**
+     * \brief Main storage for literals.
+     *
+     * Note that this cannot be a vector, as the present code relies on
+     * iterator stability when iterating over this list and adding to it inside
+     * the loop.
+     */
+    std::deque<rose_literal_id> lits;
+
+    /** \brief Quick-lookup index from literal -> index in lits. */
+    unordered_map<rose_literal_id, u32> lits_index;
+
+public:
+    std::pair<u32, bool> insert(const rose_literal_id &lit) {
+        auto it = lits_index.find(lit);
+        if (it != lits_index.end()) {
+            return {it->second, false};
+        }
+        u32 id = verify_u32(lits.size());
+        lits.push_back(lit);
+        lits_index.emplace(lit, id);
+        return {id, true};
+    }
+
+    // Erase the last num elements.
+    void erase_back(size_t num) {
+        assert(num <= lits.size());
+        for (size_t i = 0; i < num; i++) {
+            lits_index.erase(lits.back());
+            lits.pop_back();
+        }
+        assert(lits.size() == lits_index.size());
+    }
+
+    const rose_literal_id &at(u32 id) const {
+        assert(id < lits.size());
+        return lits.at(id);
+    }
+
+    using const_iterator = decltype(lits)::const_iterator;
+    const_iterator begin() const { return lits.begin(); }
+    const_iterator end() const { return lits.end(); }
+
+    size_t size() const {
+        return lits.size();
+    }
+};
 
 struct simple_anchored_info {
     simple_anchored_info(u32 min_b, u32 max_b, const ue2_literal &lit)
index 07ab7c59b39ad30b7c47f7982be89987124555bc..a46a1aeb6ca129be6f09445f5d33cf9fed6f9f9e 100644 (file)
@@ -447,7 +447,7 @@ static
 void findFloodReach(const RoseBuildImpl &tbi, const RoseVertex v,
                     set<CharReach> &flood_reach) {
     for (u32 lit_id : tbi.g[v].literals) {
-        const ue2_literal &s = tbi.literals.right.at(lit_id).s;
+        const ue2_literal &s = tbi.literals.at(lit_id).s;
         if (s.empty()) {
             continue;
         }
@@ -491,7 +491,7 @@ map<s32, CharReach> findLiteralReach(const RoseBuildImpl &build,
     map<s32, CharReach> look;
 
     for (u32 lit_id : build.g[v].literals) {
-        const rose_literal_id &lit = build.literals.right.at(lit_id);
+        const rose_literal_id &lit = build.literals.at(lit_id);
         auto lit_look = findLiteralReach(lit);
 
         if (first) {
index 64a1c9199ff7bdc803cb666a948426dd0770fc70..682a87c3885033c9628de4ba8d0f9aad45acf143 100644 (file)
@@ -211,7 +211,7 @@ bool maskFromPreds(const RoseBuildImpl &build, const rose_literal_id &id,
     }
 
     u32 u_lit_id = *(g[u].literals.begin());
-    const rose_literal_id &u_id = build.literals.right.at(u_lit_id);
+    const rose_literal_id &u_id = build.literals.at(u_lit_id);
     DEBUG_PRINTF("u has lit: %s\n", escapeString(u_id.s).c_str());
 
     // Number of characters to take from the back of u's literal.
@@ -346,9 +346,8 @@ void findMoreLiteralMasks(RoseBuildImpl &build) {
     }
 
     vector<u32> candidates;
-    for (const auto &e : build.literals.right) {
-        const u32 id = e.first;
-        const auto &lit = e.second;
+    for (u32 id = 0; id < build.literals.size(); id++) {
+        const auto &lit = build.literals.at(id);
 
         if (lit.delay || build.isDelayed(id)) {
             continue;
@@ -377,7 +376,7 @@ void findMoreLiteralMasks(RoseBuildImpl &build) {
     }
 
     for (const u32 &id : candidates) {
-        const auto &lit = build.literals.right.at(id);
+        const auto &lit = build.literals.at(id);
         auto &lit_info = build.literal_info.at(id);
 
         vector<u8> msk, cmp;
@@ -492,7 +491,7 @@ bool isNoRunsLiteral(const RoseBuildImpl &build, const u32 id,
         return false;
     }
 
-    size_t len = build.literals.right.at(id).s.length();
+    size_t len = build.literals.at(id).s.length();
     if (len > max_len) {
         DEBUG_PRINTF("long literal, requires confirm\n");
         return false;
@@ -617,7 +616,7 @@ u64a literalMinReportOffset(const RoseBuildImpl &build,
     // If this literal in the undelayed literal corresponding to some delayed
     // literals, we must take their minimum offsets into account.
     for (const u32 &delayed_id : info.delayed_ids) {
-        const auto &delayed_lit = build.literals.right.at(delayed_id);
+        const auto &delayed_lit = build.literals.at(delayed_id);
         const auto &delayed_info = build.literal_info.at(delayed_id);
         u64a delayed_min_offset = literalMinReportOffset(build, delayed_lit,
                                                          delayed_info);
@@ -682,7 +681,7 @@ MatcherProto makeMatcherProto(const RoseBuildImpl &build,
 
     for (const auto &f : fragments) {
         for (u32 id : f.lit_ids) {
-            const rose_literal_id &lit = build.literals.right.at(id);
+            const rose_literal_id &lit = build.literals.at(id);
 
             if (lit.table != table) {
                 continue; /* wrong table */
index 685d152362609ff94c2af67094c2daa85978ca87..d638e589e74384e9f70b8ce54c2d4e85df68c24c 100644 (file)
@@ -1054,14 +1054,14 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi, RoseVertex u,
     vector<pair<const rose_literal_id *, u32>> ulits;
     ulits.reserve(tbi.g[u].literals.size());
     for (u32 id : tbi.g[u].literals) {
-        ulits.push_back(make_pair(&tbi.literals.right.at(id), ulag));
+        ulits.emplace_back(&tbi.literals.at(id), ulag);
     }
 
     u32 vlag = tbi.g[v].left.lag;
     vector<pair<const rose_literal_id *, u32>> vlits;
     vlits.reserve(tbi.g[v].literals.size());
     for (u32 id : tbi.g[v].literals) {
-        vlits.push_back(make_pair(&tbi.literals.right.at(id), vlag));
+        vlits.emplace_back(&tbi.literals.at(id), vlag);
     }
 
     if (!compatibleLiteralsForMerge(ulits, vlits)) {
@@ -1130,7 +1130,7 @@ bool checkPredDelays(const RoseBuildImpl &tbi, const deque<RoseVertex> &v1,
     vector<const rose_literal_id *> pred_rose_lits;
     pred_rose_lits.reserve(pred_lits.size());
     for (const auto &p : pred_lits) {
-        pred_rose_lits.push_back(&tbi.literals.right.at(p));
+        pred_rose_lits.push_back(&tbi.literals.at(p));
     }
 
     for (auto v : v2) {
@@ -1140,7 +1140,7 @@ bool checkPredDelays(const RoseBuildImpl &tbi, const deque<RoseVertex> &v1,
         }
 
         for (const u32 vlit : tbi.g[v].literals) {
-            const rose_literal_id &vl = tbi.literals.right.at(vlit);
+            const rose_literal_id &vl = tbi.literals.at(vlit);
             assert(!vl.delay); // this should never have got this far?
             for (const auto &ul : pred_rose_lits) {
                 assert(!ul->delay); // this should never have got this far?
@@ -1195,7 +1195,7 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi,
 
         u32 ulag = tbi.g[a].left.lag;
         for (u32 id : tbi.g[a].literals) {
-            ulits.push_back(make_pair(&tbi.literals.right.at(id), ulag));
+            ulits.emplace_back(&tbi.literals.at(id), ulag);
         }
     }
 
@@ -1207,7 +1207,7 @@ bool mergeableRoseVertices(const RoseBuildImpl &tbi,
 
         u32 vlag = tbi.g[a].left.lag;
         for (u32 id : tbi.g[a].literals) {
-            vlits.push_back(make_pair(&tbi.literals.right.at(id), vlag));
+            vlits.emplace_back(&tbi.literals.at(id), vlag);
         }
     }
 
@@ -2730,7 +2730,7 @@ u32 allowedSquashDistance(const CharReach &cr, u32 min_width,
 
     /* TODO: inspect further back in the pattern */
     for (u32 lit_id : g[tv].literals) {
-        const rose_literal_id &lit = tbi.literals.right.at(lit_id);
+        const rose_literal_id &lit = tbi.literals.at(lit_id);
         if (lit.delay) {
             return 0; /* TODO: better */
         }
index f5c5ce1a2a7c430fd2b759d2de8a3653a0d72cff..01be11ef8a4cfc60a7d87801fcc4faf39954230a 100644 (file)
@@ -154,14 +154,12 @@ bool isInTable(const RoseBuildImpl &tbi, RoseVertex v,
 
     // All literals for a given vertex will be in the same table, so we need
     // only inspect the first one.
-    const auto lit_table = tbi.literals.right.at(*lit_ids.begin()).table;
+    const auto lit_table = tbi.literals.at(*lit_ids.begin()).table;
 
-#ifndef NDEBUG
     // Verify that all literals for this vertex are in the same table.
-    for (auto lit_id : lit_ids) {
-        assert(tbi.literals.right.at(lit_id).table == lit_table);
-    }
-#endif
+    assert(all_of_in(lit_ids, [&](u32 lit_id) {
+        return tbi.literals.at(lit_id).table == lit_table;
+    }));
 
     return lit_table == table;
 }
@@ -211,7 +209,7 @@ size_t RoseBuildImpl::maxLiteralLen(RoseVertex v) const {
     size_t maxlen = 0;
 
     for (const auto &lit_id : lit_ids) {
-        maxlen = max(maxlen, literals.right.at(lit_id).elength());
+        maxlen = max(maxlen, literals.at(lit_id).elength());
     }
 
     return maxlen;
@@ -224,7 +222,7 @@ size_t RoseBuildImpl::minLiteralLen(RoseVertex v) const {
     size_t minlen = ROSE_BOUND_INF;
 
     for (const auto &lit_id : lit_ids) {
-        minlen = min(minlen, literals.right.at(lit_id).elength());
+        minlen = min(minlen, literals.at(lit_id).elength());
     }
 
     return minlen;
@@ -287,12 +285,11 @@ size_t maxOverlap(const rose_literal_id &a, const rose_literal_id &b) {
 static
 const rose_literal_id &getOverlapLiteral(const RoseBuildImpl &tbi,
                                          u32 literal_id) {
-    map<u32, rose_literal_id>::const_iterator it =
-        tbi.anchoredLitSuffix.find(literal_id);
+    auto it = tbi.anchoredLitSuffix.find(literal_id);
     if (it != tbi.anchoredLitSuffix.end()) {
         return it->second;
     }
-    return tbi.literals.right.at(literal_id);
+    return tbi.literals.at(literal_id);
 }
 
 ue2_literal findNonOverlappingTail(const set<ue2_literal> &lits,
@@ -368,16 +365,14 @@ u32 RoseBuildImpl::calcSuccMaxBound(RoseVertex u) const {
 
 u32 RoseBuildImpl::getLiteralId(const ue2_literal &s, u32 delay,
                                 rose_literal_table table) {
-    DEBUG_PRINTF("getting id for %s\n", dumpString(s).c_str());
+    DEBUG_PRINTF("getting id for %s in table %d\n", dumpString(s).c_str(),
+                 table);
     assert(table != ROSE_ANCHORED);
     rose_literal_id key(s, table, delay);
-    u32 numLiterals = verify_u32(literals.left.size());
 
-    RoseLiteralMap::iterator it;
-    bool inserted;
-    tie(it, inserted)
-        = literals.insert(RoseLiteralMap::value_type(key, numLiterals));
-    u32 id = it->right;
+    auto m = literals.insert(key);
+    u32 id = m.first;
+    bool inserted = m.second;
 
     if (inserted) {
         literal_info.push_back(rose_literal_info());
@@ -457,19 +452,17 @@ rose_literal_id::rose_literal_id(const ue2_literal &s_in,
 u32 RoseBuildImpl::getLiteralId(const ue2_literal &s, const vector<u8> &msk,
                                 const vector<u8> &cmp, u32 delay,
                                 rose_literal_table table) {
-    DEBUG_PRINTF("getting id for %s\n", dumpString(s).c_str());
+    DEBUG_PRINTF("getting id for %s in table %d\n", dumpString(s).c_str(),
+                 table);
     assert(table != ROSE_ANCHORED);
     rose_literal_id key(s, msk, cmp, table, delay);
-    u32 numLiterals = verify_u32(literals.left.size());
 
     /* ue2_literals are always uppercased if nocase and must have an
      * alpha char */
 
-    RoseLiteralMap::iterator it;
-    bool inserted;
-    tie(it, inserted) = literals.insert(
-            RoseLiteralMap::value_type(key, numLiterals));
-    u32 id = it->right;
+    auto m = literals.insert(key);
+    u32 id = m.first;
+    bool inserted = m.second;
 
     if (inserted) {
         literal_info.push_back(rose_literal_info());
@@ -488,16 +481,12 @@ u32 RoseBuildImpl::getLiteralId(const ue2_literal &s, const vector<u8> &msk,
 
 u32 RoseBuildImpl::getNewLiteralId() {
     rose_literal_id key(ue2_literal(), ROSE_ANCHORED, 0);
-    u32 numLiterals = verify_u32(literals.left.size());
+    u32 numLiterals = verify_u32(literals.size());
     key.distinctiveness = numLiterals;
 
-    RoseLiteralMap::iterator it;
-    bool inserted;
-    tie(it, inserted)
-        = literals.insert(RoseLiteralMap::value_type(key, numLiterals));
-    u32 id = it->right;
-
-    assert(inserted);
+    auto m = literals.insert(key);
+    assert(m.second);
+    u32 id = m.first;
 
     literal_info.push_back(rose_literal_info());
     assert(literal_info.size() == id + 1);
index 8d0306ae75bc2321ad7c239845a32fa068effafa..6dfe3507c7af3f608255827082c6008d766fe310 100644 (file)
@@ -349,7 +349,7 @@ void makeAnchoredLiteralDelay(const RoseBuildImpl &build,
                               const ProgramBuild &prog_build, u32 lit_id,
                               RoseProgram &program) {
     // Only relevant for literals in the anchored table.
-    const rose_literal_id &lit = build.literals.right.at(lit_id);
+    const rose_literal_id &lit = build.literals.at(lit_id);
     if (lit.table != ROSE_ANCHORED) {
         return;
     }
@@ -686,7 +686,7 @@ void makePushDelayedInstructions(const RoseLiteralMap &literals,
         DEBUG_PRINTF("delayed lit id %u\n", delayed_lit_id);
         assert(contains(prog_build.delay_programs, delayed_lit_id));
         u32 delay_id = prog_build.delay_programs.at(delayed_lit_id);
-        const auto &delay_lit = literals.right.at(delayed_lit_id);
+        const auto &delay_lit = literals.at(delayed_lit_id);
         delay_instructions.emplace_back(verify_u8(delay_lit.delay), delay_id);
     }
 
@@ -1335,7 +1335,7 @@ void makeCheckLitMaskInstruction(const RoseBuildImpl &build,
 
     vector<LookEntry> look;
 
-    const ue2_literal &s = build.literals.right.at(lit_id).s;
+    const ue2_literal &s = build.literals.at(lit_id).s;
     DEBUG_PRINTF("building mask for lit %u: %s\n", lit_id,
                  dumpString(s).c_str());
     assert(s.length() <= MAX_MASK2_WIDTH);
@@ -1369,7 +1369,7 @@ void makeCheckLitEarlyInstruction(const RoseBuildImpl &build, u32 lit_id,
         return;
     }
 
-    const auto &lit = build.literals.right.at(lit_id);
+    const auto &lit = build.literals.at(lit_id);
     size_t min_len = lit.elength();
     u32 min_offset = findMinOffset(build, lit_id);
     DEBUG_PRINTF("has min_len=%zu, min_offset=%u, global min is %u\n", min_len,
@@ -1404,7 +1404,7 @@ void makeGroupCheckInstruction(const RoseBuildImpl &build, u32 lit_id,
 static
 bool hasDelayedLiteral(const RoseBuildImpl &build,
                        const vector<RoseEdge> &lit_edges) {
-    auto is_delayed = bind(&RoseBuildImpl::isDelayed, &build, _1);
+    auto is_delayed = [&build](u32 lit_id) { return build.isDelayed(lit_id); };
     for (const auto &e : lit_edges) {
         auto v = target(e, build.g);
         const auto &lits = build.g[v].literals;
@@ -1425,7 +1425,7 @@ RoseProgram makeLitInitialProgram(const RoseBuildImpl &build,
 
     // Check long literal info.
     if (!build.isDelayed(lit_id)) {
-        makeCheckLiteralInstruction(build.literals.right.at(lit_id),
+        makeCheckLiteralInstruction(build.literals.at(lit_id),
                                     prog_build.longLitLengthThreshold,
                                     program, build.cc);
     }
@@ -2121,7 +2121,7 @@ RoseProgram makeDelayRebuildProgram(const RoseBuildImpl &build,
 
         RoseProgram prog;
         if (!build.isDelayed(lit_id)) {
-            makeCheckLiteralInstruction(build.literals.right.at(lit_id),
+            makeCheckLiteralInstruction(build.literals.at(lit_id),
                                         prog_build.longLitLengthThreshold, prog,
                                         build.cc);
         }
index f8174d74fef0c57be7ef29b645adde94ad37bbb0..0e78ec7db43c69a5a5f364d1563a1a0d75a1ca81 100644 (file)
@@ -328,9 +328,9 @@ bool canMergeLiterals(RoseVertex a, RoseVertex b, const RoseBuildImpl &build) {
 
     // Otherwise, all the literals involved must have the same length.
     for (u32 a_id : lits_a) {
-        const rose_literal_id &la = build.literals.right.at(a_id);
+        const rose_literal_id &la = build.literals.at(a_id);
         for (u32 b_id : lits_b) {
-            const rose_literal_id &lb = build.literals.right.at(b_id);
+            const rose_literal_id &lb = build.literals.at(b_id);
 
             if (la.elength() != lb.elength()) {
                 DEBUG_PRINTF("bad merge %zu!=%zu '%s', '%s'\n", la.elength(),
@@ -1483,7 +1483,7 @@ void splitByLiteralTable(const RoseBuildImpl &build,
     auto make_split_key = [&](RoseVertex v) {
         const auto &lits = g[v].literals;
         assert(!lits.empty());
-        return build.literals.right.at(*lits.begin()).table;
+        return build.literals.at(*lits.begin()).table;
     };
     splitAndFilterBuckets(buckets, make_split_key);
 }