mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
ng_calc_components: rework to move graphs
Rather than cloning graphs for output, rework calc components so that it moves them.
This commit is contained in:
parent
5dfae12a62
commit
ba867ebaff
@ -276,13 +276,12 @@ void addExpression(NG &ng, unsigned index, const char *expression,
|
|||||||
throw CompileError("Internal error.");
|
throw CompileError("Internal error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &g = *built_expr.g;
|
if (!pe.expr.allow_vacuous && matches_everywhere(*built_expr.g)) {
|
||||||
if (!pe.expr.allow_vacuous && matches_everywhere(g)) {
|
|
||||||
throw CompileError("Pattern matches empty buffer; use "
|
throw CompileError("Pattern matches empty buffer; use "
|
||||||
"HS_FLAG_ALLOWEMPTY to enable support.");
|
"HS_FLAG_ALLOWEMPTY to enable support.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ng.addGraph(built_expr.expr, g)) {
|
if (!ng.addGraph(built_expr.expr, std::move(built_expr.g))) {
|
||||||
DEBUG_PRINTF("NFA addGraph failed on ID %u.\n", pe.expr.report);
|
DEBUG_PRINTF("NFA addGraph failed on ID %u.\n", pe.expr.report);
|
||||||
throw CompileError("Error compiling expression.");
|
throw CompileError("Error compiling expression.");
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,10 @@ bool processComponents(NG &ng, ExpressionInfo &expr,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NG::addGraph(ExpressionInfo &expr, NGHolder &g) {
|
bool NG::addGraph(ExpressionInfo &expr, unique_ptr<NGHolder> g_ptr) {
|
||||||
|
assert(g_ptr);
|
||||||
|
NGHolder &g = *g_ptr;
|
||||||
|
|
||||||
// remove reports that aren't on vertices connected to accept.
|
// remove reports that aren't on vertices connected to accept.
|
||||||
clearReports(g);
|
clearReports(g);
|
||||||
|
|
||||||
@ -431,15 +434,16 @@ bool NG::addGraph(ExpressionInfo &expr, NGHolder &g) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split the graph into a set of connected components.
|
// Split the graph into a set of connected components and process those.
|
||||||
|
// Note: this invalidates g_ptr.
|
||||||
|
|
||||||
deque<unique_ptr<NGHolder>> g_comp = calcComponents(g);
|
auto g_comp = calcComponents(std::move(g_ptr));
|
||||||
assert(!g_comp.empty());
|
assert(!g_comp.empty());
|
||||||
|
|
||||||
if (!som) {
|
if (!som) {
|
||||||
for (u32 i = 0; i < g_comp.size(); i++) {
|
for (auto &gc : g_comp) {
|
||||||
assert(g_comp[i]);
|
assert(gc);
|
||||||
reformLeadingDots(*g_comp[i]);
|
reformLeadingDots(*gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
recalcComponents(g_comp);
|
recalcComponents(g_comp);
|
||||||
@ -453,12 +457,11 @@ bool NG::addGraph(ExpressionInfo &expr, NGHolder &g) {
|
|||||||
// have another shot at accepting the graph.
|
// have another shot at accepting the graph.
|
||||||
|
|
||||||
if (cc.grey.prefilterReductions && expr.prefilter) {
|
if (cc.grey.prefilterReductions && expr.prefilter) {
|
||||||
for (u32 i = 0; i < g_comp.size(); i++) {
|
for (auto &gc : g_comp) {
|
||||||
if (!g_comp[i]) {
|
if (!gc) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
prefilterReductions(*gc, cc);
|
||||||
prefilterReductions(*g_comp[i], cc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processComponents(*this, expr, g_comp, som)) {
|
if (processComponents(*this, expr, g_comp, som)) {
|
||||||
|
@ -70,7 +70,7 @@ public:
|
|||||||
|
|
||||||
/** \brief Consumes a pattern, returns false or throws a CompileError
|
/** \brief Consumes a pattern, returns false or throws a CompileError
|
||||||
* exception if the graph cannot be consumed. */
|
* exception if the graph cannot be consumed. */
|
||||||
bool addGraph(ExpressionInfo &expr, NGHolder &h);
|
bool addGraph(ExpressionInfo &expr, std::unique_ptr<NGHolder> g_ptr);
|
||||||
|
|
||||||
/** \brief Consumes a graph, cut-down version of addGraph for use by SOM
|
/** \brief Consumes a graph, cut-down version of addGraph for use by SOM
|
||||||
* processing. */
|
* processing. */
|
||||||
|
@ -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
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -245,31 +245,33 @@ void renumberVertices(NFAUndirectedGraph &ug) {
|
|||||||
* one or more connected components, adding them to the comps deque.
|
* one or more connected components, adding them to the comps deque.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
void splitIntoComponents(unique_ptr<NGHolder> g,
|
||||||
|
deque<unique_ptr<NGHolder>> &comps,
|
||||||
const depth &max_head_depth,
|
const depth &max_head_depth,
|
||||||
const depth &max_tail_depth, bool *shell_comp) {
|
const depth &max_tail_depth, bool *shell_comp) {
|
||||||
DEBUG_PRINTF("graph has %zu vertices\n", num_vertices(g));
|
DEBUG_PRINTF("graph has %zu vertices\n", num_vertices(*g));
|
||||||
|
|
||||||
assert(shell_comp);
|
assert(shell_comp);
|
||||||
*shell_comp = false;
|
*shell_comp = false;
|
||||||
|
|
||||||
// Compute "shell" head and tail subgraphs.
|
// Compute "shell" head and tail subgraphs.
|
||||||
vector<NFAVertexBidiDepth> depths;
|
vector<NFAVertexBidiDepth> depths;
|
||||||
calcDepths(g, depths);
|
calcDepths(*g, depths);
|
||||||
auto head_shell = findHeadShell(g, depths, max_head_depth);
|
auto head_shell = findHeadShell(*g, depths, max_head_depth);
|
||||||
auto tail_shell = findTailShell(g, depths, max_tail_depth);
|
auto tail_shell = findTailShell(*g, depths, max_tail_depth);
|
||||||
for (auto v : head_shell) {
|
for (auto v : head_shell) {
|
||||||
tail_shell.erase(v);
|
tail_shell.erase(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head_shell.size() + tail_shell.size() + N_SPECIALS >= num_vertices(g)) {
|
if (head_shell.size() + tail_shell.size() + N_SPECIALS >=
|
||||||
|
num_vertices(*g)) {
|
||||||
DEBUG_PRINTF("all in shell component\n");
|
DEBUG_PRINTF("all in shell component\n");
|
||||||
comps.push_back(cloneHolder(g));
|
comps.push_back(std::move(g));
|
||||||
*shell_comp = true;
|
*shell_comp = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<NFAEdge> shell_edges = findShellEdges(g, head_shell, tail_shell);
|
vector<NFAEdge> shell_edges = findShellEdges(*g, head_shell, tail_shell);
|
||||||
|
|
||||||
DEBUG_PRINTF("%zu vertices in head, %zu in tail, %zu shell edges\n",
|
DEBUG_PRINTF("%zu vertices in head, %zu in tail, %zu shell edges\n",
|
||||||
head_shell.size(), tail_shell.size(), shell_edges.size());
|
head_shell.size(), tail_shell.size(), shell_edges.size());
|
||||||
@ -277,7 +279,7 @@ void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
|||||||
NFAUndirectedGraph ug;
|
NFAUndirectedGraph ug;
|
||||||
ue2::unordered_map<NFAVertex, NFAUndirectedVertex> old2new;
|
ue2::unordered_map<NFAVertex, NFAUndirectedVertex> old2new;
|
||||||
|
|
||||||
createUnGraph(g, true, true, ug, old2new);
|
createUnGraph(*g, true, true, ug, old2new);
|
||||||
|
|
||||||
// Construct reverse mapping.
|
// Construct reverse mapping.
|
||||||
ue2::unordered_map<NFAUndirectedVertex, NFAVertex> new2old;
|
ue2::unordered_map<NFAUndirectedVertex, NFAVertex> new2old;
|
||||||
@ -298,7 +300,7 @@ void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
|||||||
assert(num > 0);
|
assert(num > 0);
|
||||||
if (num == 1 && shell_edges.empty()) {
|
if (num == 1 && shell_edges.empty()) {
|
||||||
DEBUG_PRINTF("single component\n");
|
DEBUG_PRINTF("single component\n");
|
||||||
comps.push_back(cloneHolder(g));
|
comps.push_back(std::move(g));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,7 +315,7 @@ void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
|||||||
assert(contains(new2old, uv));
|
assert(contains(new2old, uv));
|
||||||
NFAVertex v = new2old.at(uv);
|
NFAVertex v = new2old.at(uv);
|
||||||
verts[c].push_back(v);
|
verts[c].push_back(v);
|
||||||
DEBUG_PRINTF("vertex %zu is in comp %u\n", g[v].index, c);
|
DEBUG_PRINTF("vertex %zu is in comp %u\n", (*g)[v].index, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
ue2::unordered_map<NFAVertex, NFAVertex> v_map; // temp map for fillHolder
|
ue2::unordered_map<NFAVertex, NFAVertex> v_map; // temp map for fillHolder
|
||||||
@ -328,12 +330,12 @@ void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
|||||||
|
|
||||||
auto gc = ue2::make_unique<NGHolder>();
|
auto gc = ue2::make_unique<NGHolder>();
|
||||||
v_map.clear();
|
v_map.clear();
|
||||||
fillHolder(gc.get(), g, vv, &v_map);
|
fillHolder(gc.get(), *g, vv, &v_map);
|
||||||
|
|
||||||
// Remove shell edges, which will get their own component.
|
// Remove shell edges, which will get their own component.
|
||||||
for (const auto &e : shell_edges) {
|
for (const auto &e : shell_edges) {
|
||||||
auto cu = v_map.at(source(e, g));
|
auto cu = v_map.at(source(e, *g));
|
||||||
auto cv = v_map.at(target(e, g));
|
auto cv = v_map.at(target(e, *g));
|
||||||
assert(edge(cu, cv, *gc).second);
|
assert(edge(cu, cv, *gc).second);
|
||||||
remove_edge(cu, cv, *gc);
|
remove_edge(cu, cv, *gc);
|
||||||
}
|
}
|
||||||
@ -352,7 +354,7 @@ void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
|||||||
|
|
||||||
auto gc = ue2::make_unique<NGHolder>();
|
auto gc = ue2::make_unique<NGHolder>();
|
||||||
v_map.clear();
|
v_map.clear();
|
||||||
fillHolder(gc.get(), g, vv, &v_map);
|
fillHolder(gc.get(), *g, vv, &v_map);
|
||||||
|
|
||||||
pruneUseless(*gc);
|
pruneUseless(*gc);
|
||||||
DEBUG_PRINTF("shell edge component %zu has %zu vertices\n",
|
DEBUG_PRINTF("shell edge component %zu has %zu vertices\n",
|
||||||
@ -374,26 +376,26 @@ void splitIntoComponents(const NGHolder &g, deque<unique_ptr<NGHolder>> &comps,
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
deque<unique_ptr<NGHolder>> calcComponents(const NGHolder &g) {
|
deque<unique_ptr<NGHolder>> calcComponents(unique_ptr<NGHolder> g) {
|
||||||
deque<unique_ptr<NGHolder>> comps;
|
deque<unique_ptr<NGHolder>> comps;
|
||||||
|
|
||||||
// For trivial cases, we needn't bother running the full
|
// For trivial cases, we needn't bother running the full
|
||||||
// connected_components algorithm.
|
// connected_components algorithm.
|
||||||
if (isAlternationOfClasses(g)) {
|
if (isAlternationOfClasses(*g)) {
|
||||||
comps.push_back(cloneHolder(g));
|
comps.push_back(std::move(g));
|
||||||
return comps;
|
return comps;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shell_comp = false;
|
bool shell_comp = false;
|
||||||
splitIntoComponents(g, comps, MAX_HEAD_SHELL_DEPTH, MAX_TAIL_SHELL_DEPTH,
|
splitIntoComponents(std::move(g), comps, MAX_HEAD_SHELL_DEPTH,
|
||||||
&shell_comp);
|
MAX_TAIL_SHELL_DEPTH, &shell_comp);
|
||||||
|
|
||||||
if (shell_comp) {
|
if (shell_comp) {
|
||||||
DEBUG_PRINTF("re-running on shell comp\n");
|
DEBUG_PRINTF("re-running on shell comp\n");
|
||||||
assert(!comps.empty());
|
assert(!comps.empty());
|
||||||
auto sc = move(comps.back());
|
auto sc = std::move(comps.back());
|
||||||
comps.pop_back();
|
comps.pop_back();
|
||||||
splitIntoComponents(*sc, comps, 0, 0, &shell_comp);
|
splitIntoComponents(std::move(sc), comps, 0, 0, &shell_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_PRINTF("finished; split into %zu components\n", comps.size());
|
DEBUG_PRINTF("finished; split into %zu components\n", comps.size());
|
||||||
@ -409,14 +411,13 @@ void recalcComponents(deque<unique_ptr<NGHolder>> &comps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isAlternationOfClasses(*gc)) {
|
if (isAlternationOfClasses(*gc)) {
|
||||||
out.push_back(move(gc));
|
out.push_back(std::move(gc));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto gc_comps = calcComponents(*gc);
|
auto gc_comps = calcComponents(std::move(gc));
|
||||||
for (auto &elem : gc_comps) {
|
out.insert(end(out), std::make_move_iterator(begin(gc_comps)),
|
||||||
out.push_back(move(elem));
|
std::make_move_iterator(end(gc_comps)));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace comps with our recalculated list.
|
// Replace comps with our recalculated list.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Intel Corporation
|
* Copyright (c) 2015-2017, Intel Corporation
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -42,7 +42,8 @@ class NGHolder;
|
|||||||
|
|
||||||
bool isAlternationOfClasses(const NGHolder &g);
|
bool isAlternationOfClasses(const NGHolder &g);
|
||||||
|
|
||||||
std::deque<std::unique_ptr<NGHolder>> calcComponents(const NGHolder &g);
|
std::deque<std::unique_ptr<NGHolder>>
|
||||||
|
calcComponents(std::unique_ptr<NGHolder> g);
|
||||||
|
|
||||||
void recalcComponents(std::deque<std::unique_ptr<NGHolder>> &comps);
|
void recalcComponents(std::deque<std::unique_ptr<NGHolder>> &comps);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Intel Corporation
|
* Copyright (c) 2015-2017, Intel Corporation
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are met:
|
* modification, are permitted provided that the following conditions are met:
|
||||||
@ -33,13 +33,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "nfagraph_common.h"
|
#include "nfagraph_common.h"
|
||||||
#include "grey.h"
|
|
||||||
#include "hs.h"
|
|
||||||
#include "compiler/compiler.h"
|
|
||||||
#include "nfagraph/ng.h"
|
#include "nfagraph/ng.h"
|
||||||
#include "nfagraph/ng_builder.h"
|
|
||||||
#include "nfagraph/ng_calc_components.h"
|
#include "nfagraph/ng_calc_components.h"
|
||||||
#include "util/target_info.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ue2;
|
using namespace ue2;
|
||||||
@ -48,7 +43,7 @@ TEST(NFAGraph, CalcComp1) {
|
|||||||
auto graph = constructGraph("abc|def|ghi", 0);
|
auto graph = constructGraph("abc|def|ghi", 0);
|
||||||
ASSERT_TRUE(graph != nullptr);
|
ASSERT_TRUE(graph != nullptr);
|
||||||
|
|
||||||
deque<unique_ptr<NGHolder>> comps = calcComponents(*graph);
|
auto comps = calcComponents(std::move(graph));
|
||||||
ASSERT_EQ(3, comps.size());
|
ASSERT_EQ(3, comps.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +51,7 @@ TEST(NFAGraph, CalcComp2) {
|
|||||||
auto graph = constructGraph("a|b|c|d|e|f|g|h|i", 0);
|
auto graph = constructGraph("a|b|c|d|e|f|g|h|i", 0);
|
||||||
ASSERT_TRUE(graph != nullptr);
|
ASSERT_TRUE(graph != nullptr);
|
||||||
|
|
||||||
deque<unique_ptr<NGHolder>> comps = calcComponents(*graph);
|
auto comps = calcComponents(std::move(graph));
|
||||||
|
|
||||||
// We should be identifying this as a trivial case and not splitting it.
|
// We should be identifying this as a trivial case and not splitting it.
|
||||||
ASSERT_EQ(1, comps.size());
|
ASSERT_EQ(1, comps.size());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user