From abbd54889959425c77689d30d1764079f62a8ecc Mon Sep 17 00:00:00 2001 From: Justin Viiret Date: Fri, 13 Nov 2015 14:36:28 +1100 Subject: [PATCH] ng_execute: update interface to use flat_set This changes all the execute_graph() interfaces so that instead of mutating a std::set of vertices, they accept an initial flat_set of states and return a resultant flat_set of states after execution. (Note that internally execute_graph() still uses bitsets) This is both faster and more flexible. --- src/nfagraph/ng_execute.cpp | 86 +++++++++++++++++---------------- src/nfagraph/ng_execute.h | 22 +++++---- src/nfagraph/ng_som.cpp | 15 +++--- src/nfagraph/ng_som_util.cpp | 8 +-- src/rose/rose_build_compile.cpp | 17 ++++--- 5 files changed, 79 insertions(+), 69 deletions(-) diff --git a/src/nfagraph/ng_execute.cpp b/src/nfagraph/ng_execute.cpp index aebfa712..92bef737 100644 --- a/src/nfagraph/ng_execute.cpp +++ b/src/nfagraph/ng_execute.cpp @@ -125,61 +125,62 @@ void execute_graph_i(const NGHolder &g, const vector &info, } static -void fillStateBitset(const NGHolder &g, const set &in, - dynamic_bitset<> &out) { - out.reset(); - for (auto v : in) { +dynamic_bitset<> makeStateBitset(const NGHolder &g, + const flat_set &in) { + dynamic_bitset<> work_states(num_vertices(g)); + for (const auto &v : in) { u32 idx = g[v].index; - out.set(idx); + work_states.set(idx); } + return work_states; } static -void fillVertexSet(const dynamic_bitset<> &in, - const vector &info, set &out) { - out.clear(); +flat_set getVertices(const dynamic_bitset<> &in, + const vector &info) { + flat_set out; for (size_t i = in.find_first(); i != in.npos; i = in.find_next(i)) { out.insert(info[i].vertex); } + return out; } static -void fillInfoTable(const NGHolder &g, vector &info) { - info.resize(num_vertices(g)); +vector makeInfoTable(const NGHolder &g) { + vector info(num_vertices(g)); for (auto v : vertices_range(g)) { u32 idx = g[v].index; const CharReach &cr = g[v].char_reach; assert(idx < info.size()); info[idx] = StateInfo(v, cr); } + return info; } -void execute_graph(const NGHolder &g, const ue2_literal &input, - set *states, bool kill_sds) { +flat_set execute_graph(const NGHolder &g, const ue2_literal &input, + const flat_set &initial_states, + bool kill_sds) { assert(hasCorrectlyNumberedVertices(g)); - vector info; - fillInfoTable(g, info); - dynamic_bitset<> work_states(num_vertices(g)); - fillStateBitset(g, *states, work_states); + auto info = makeInfoTable(g); + auto work_states = makeStateBitset(g, initial_states); execute_graph_i(g, info, input, &work_states, kill_sds); - fillVertexSet(work_states, info, *states); + return getVertices(work_states, info); } -void execute_graph(const NGHolder &g, const vector &input, - set *states) { +flat_set execute_graph(const NGHolder &g, + const vector &input, + const flat_set &initial_states) { assert(hasCorrectlyNumberedVertices(g)); - vector info; - fillInfoTable(g, info); - dynamic_bitset<> work_states(num_vertices(g)); - fillStateBitset(g, *states, work_states); + auto info = makeInfoTable(g); + auto work_states = makeStateBitset(g, initial_states); execute_graph_i(g, info, input, &work_states, false); - fillVertexSet(work_states, info, *states); + return getVertices(work_states, info); } typedef boost::reverse_graph RevNFAGraph; @@ -276,9 +277,10 @@ private: }; } // namespace -void execute_graph(const NGHolder &running_g, const NGHolder &input_dag, - const set &input_start_states, - set *states) { +flat_set execute_graph(const NGHolder &running_g, + const NGHolder &input_dag, + const flat_set &input_start_states, + const flat_set &initial_states) { DEBUG_PRINTF("g has %zu vertices, input_dag has %zu vertices\n", num_vertices(running_g), num_vertices(input_dag)); assert(hasCorrectlyNumberedVertices(running_g)); @@ -290,10 +292,8 @@ void execute_graph(const NGHolder &running_g, const NGHolder &input_dag, RevNFAGraph revg(input_dag.g); map > dfs_states; - vector info; - fillInfoTable(running_g, info); - dynamic_bitset<> input_fs(num_vertices(running_g)); - fillStateBitset(running_g, *states, input_fs); + auto info = makeInfoTable(running_g); + auto input_fs = makeStateBitset(running_g, initial_states); for (auto v : input_start_states) { dfs_states[v] = input_fs; @@ -303,21 +303,25 @@ void execute_graph(const NGHolder &running_g, const NGHolder &input_dag, eg_visitor(running_g, info, input_dag, dfs_states), make_assoc_property_map(colours)); - fillVertexSet(dfs_states[input_dag.accept], info, *states); + auto states = getVertices(dfs_states[input_dag.accept], info); #ifdef DEBUG - DEBUG_PRINTF(" output rstates:"); - for (auto v : *states) { - printf(" %u", running_g[v].index); - } - printf("\n"); + DEBUG_PRINTF(" output rstates:"); + for (const auto &v : states) { + printf(" %u", running_g[v].index); + } + printf("\n"); #endif + + return states; } -void execute_graph(const NGHolder &running_g, const NGHolder &input_dag, - set *states) { - set input_start_states = {input_dag.start, input_dag.startDs}; - execute_graph(running_g, input_dag, input_start_states, states); +flat_set execute_graph(const NGHolder &running_g, + const NGHolder &input_dag, + const flat_set &initial_states) { + auto input_start_states = {input_dag.start, input_dag.startDs}; + return execute_graph(running_g, input_dag, input_start_states, + initial_states); } } // namespace ue2 diff --git a/src/nfagraph/ng_execute.h b/src/nfagraph/ng_execute.h index 80fdcbd5..e2c7c72d 100644 --- a/src/nfagraph/ng_execute.h +++ b/src/nfagraph/ng_execute.h @@ -35,8 +35,8 @@ #define NG_EXECUTE_H #include "ng_holder.h" +#include "util/ue2_containers.h" -#include #include namespace ue2 { @@ -44,23 +44,25 @@ namespace ue2 { class CharReach; struct ue2_literal; -void execute_graph(const NGHolder &g, const ue2_literal &input, - std::set *states, bool kill_sds = false); +flat_set execute_graph(const NGHolder &g, const ue2_literal &input, + const flat_set &initial, + bool kill_sds = false); -void execute_graph(const NGHolder &g, const std::vector &input, - std::set *states); +flat_set execute_graph(const NGHolder &g, + const std::vector &input, + const flat_set &initial); /** on exit, states contains any state which may still be enabled after * receiving an input which corresponds to some path through the input_dag from * start or startDs to accept. input_dag MUST be acyclic aside from self-loops. */ -void execute_graph(const NGHolder &g, const NGHolder &input_dag, - std::set *states); +flat_set execute_graph(const NGHolder &g, const NGHolder &input_dag, + const flat_set &initial); /* as above, but able to specify the source states for the input graph */ -void execute_graph(const NGHolder &g, const NGHolder &input_dag, - const std::set &input_start_states, - std::set *states); +flat_set execute_graph(const NGHolder &g, const NGHolder &input_dag, + const flat_set &input_start_states, + const flat_set &initial); } // namespace ue2 diff --git a/src/nfagraph/ng_som.cpp b/src/nfagraph/ng_som.cpp index 90ebb5c3..f26b62aa 100644 --- a/src/nfagraph/ng_som.cpp +++ b/src/nfagraph/ng_som.cpp @@ -266,7 +266,7 @@ bool validateEXSL(const NGHolder &g, const vector escapes_vec(1, escapes); const vector notescapes_vec(1, ~escapes); - set states; + ue2::flat_set states; /* turn on all states past the prefix */ DEBUG_PRINTF("region %u is cutover\n", region); for (auto v : vertices_range(g)) { @@ -276,20 +276,20 @@ bool validateEXSL(const NGHolder &g, } /* process the escapes */ - execute_graph(g, escapes_vec, &states); + states = execute_graph(g, escapes_vec, states); /* flood with any number of not escapes */ - set prev_states; + ue2::flat_set prev_states; while (prev_states != states) { prev_states = states; - execute_graph(g, notescapes_vec, &states); + states = execute_graph(g, notescapes_vec, states); insert(&states, prev_states); } /* find input starts to use for when we are running the prefix through as * when the escape character arrives we may be in matching the prefix * already */ - set prefix_start_states; + ue2::flat_set prefix_start_states; for (auto v : vertices_range(prefix)) { if (v != prefix.accept && v != prefix.acceptEod /* and as we have already made it past the prefix once */ @@ -298,11 +298,12 @@ bool validateEXSL(const NGHolder &g, } } - execute_graph(prefix, escapes_vec, &prefix_start_states); + prefix_start_states = + execute_graph(prefix, escapes_vec, prefix_start_states); assert(contains(prefix_start_states, prefix.startDs)); /* see what happens after we feed it the prefix */ - execute_graph(g, prefix, prefix_start_states, &states); + states = execute_graph(g, prefix, prefix_start_states, states); for (auto v : states) { assert(v != g.accept && v != g.acceptEod); /* no cr -> should never be diff --git a/src/nfagraph/ng_som_util.cpp b/src/nfagraph/ng_som_util.cpp index 7f487f89..a0829451 100644 --- a/src/nfagraph/ng_som_util.cpp +++ b/src/nfagraph/ng_som_util.cpp @@ -136,7 +136,7 @@ bool firstMatchIsFirst(const NGHolder &p) { return false; } - set states; + ue2::flat_set states; /* turn on all states (except starts - avoid suffix matches) */ /* If we were doing (1) we would also except states leading to accepts - avoid prefix matches */ @@ -149,7 +149,7 @@ bool firstMatchIsFirst(const NGHolder &p) { } /* run the prefix the main graph */ - execute_graph(p, p, &states); + states = execute_graph(p, p, states); for (auto v : states) { /* need to check if this vertex may represent an infix match - ie @@ -313,7 +313,7 @@ bool sentClearsTail(const NGHolder &g, */ u32 first_bad_region = ~0U; - set states; + ue2::flat_set states; /* turn on all states */ DEBUG_PRINTF("region %u is cutover\n", last_head_region); for (auto v : vertices_range(g)) { @@ -327,7 +327,7 @@ bool sentClearsTail(const NGHolder &g, } /* run the prefix the main graph */ - execute_graph(g, sent, &states); + states = execute_graph(g, sent, states); /* .. and check if we are left with anything in the tail region */ for (auto v : states) { diff --git a/src/rose/rose_build_compile.cpp b/src/rose/rose_build_compile.cpp index 34e76269..a2bd971e 100644 --- a/src/rose/rose_build_compile.cpp +++ b/src/rose/rose_build_compile.cpp @@ -1631,20 +1631,23 @@ bool triggerKillsRoseGraph(const RoseBuildImpl &tbi, const left_id &left, assert(left.graph()); const NGHolder &h = *left.graph(); + ue2::flat_set all_states; + insert(&all_states, vertices(h)); + assert(out_degree(h.startDs, h) == 1); /* triggered don't use sds */ + DEBUG_PRINTF("removing sds\n"); + all_states.erase(h.startDs); + + ue2::flat_set states; + /* check each pred literal to see if they all kill previous graph * 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 ue2_literal s = findNonOverlappingTail(all_lits, pred_lit.s); - set states; - insert(&states, vertices(h)); - assert(out_degree(h.startDs, h) == 1); /* triggered don't use sds */ - DEBUG_PRINTF("removing sds\n"); - states.erase(h.startDs); DEBUG_PRINTF("running graph %zu\n", states.size()); - execute_graph(h, s, &states, true); - DEBUG_PRINTF("ran\n"); + states = execute_graph(h, s, all_states, true); + DEBUG_PRINTF("ran, %zu states on\n", states.size()); if (!states.empty()) { return false;