OutfixInfo: use boost::variant for engines

This commit is contained in:
Justin Viiret 2016-04-15 16:41:35 +10:00 committed by Matthew Barr
parent fa27025bcb
commit 32c866a8f9
6 changed files with 154 additions and 96 deletions

View File

@ -1776,11 +1776,13 @@ bool RoseBuildImpl::addOutfix(const NGHolder &h, const raw_som_dfa &haig) {
bool RoseBuildImpl::addOutfix(const raw_puff &rp) { bool RoseBuildImpl::addOutfix(const raw_puff &rp) {
if (!mpv_outfix) { if (!mpv_outfix) {
mpv_outfix = make_unique<OutfixInfo>(); mpv_outfix = make_unique<OutfixInfo>(MpvProto());
mpv_outfix->chained = true; mpv_outfix->chained = true;
} }
mpv_outfix->mpv.puffettes.push_back(rp); auto *mpv = mpv_outfix->mpv();
assert(mpv);
mpv->puffettes.push_back(rp);
mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */ mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */
mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats)); mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats));
@ -1800,11 +1802,13 @@ bool RoseBuildImpl::addOutfix(const raw_puff &rp) {
bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out, bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out,
u32 *event_out) { u32 *event_out) {
if (!mpv_outfix) { if (!mpv_outfix) {
mpv_outfix = make_unique<OutfixInfo>(); mpv_outfix = make_unique<OutfixInfo>(MpvProto());
mpv_outfix->chained = true; mpv_outfix->chained = true;
} }
mpv_outfix->mpv.triggered_puffettes.push_back(rp); auto *mpv = mpv_outfix->mpv();
assert(mpv);
mpv->triggered_puffettes.push_back(rp);
mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */ mpv_outfix->maxBAWidth = ROSE_BOUND_INF; /* not ba */
mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats)); mpv_outfix->minWidth = min(mpv_outfix->minWidth, depth(rp.repeats));
@ -1816,7 +1820,7 @@ bool RoseBuildImpl::addChainTail(const raw_puff &rp, u32 *queue_out,
* the caller */ * the caller */
*queue_out = mpv_outfix->get_queue(qif); *queue_out = mpv_outfix->get_queue(qif);
*event_out = MQE_TOP_FIRST + mpv_outfix->mpv.triggered_puffettes.size() - 1; *event_out = MQE_TOP_FIRST + mpv->triggered_puffettes.size() - 1;
return true; /* failure is not yet an option */ return true; /* failure is not yet an option */
} }

View File

@ -1264,14 +1264,14 @@ aligned_unique_ptr<NFA> buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) {
const ReportManager &rm = tbi.rm; const ReportManager &rm = tbi.rm;
aligned_unique_ptr<NFA> n; aligned_unique_ptr<NFA> n;
if (outfix.rdfa) { if (auto *rdfa = outfix.rdfa()) {
// Unleash the McClellan! // Unleash the McClellan!
n = mcclellanCompile(*outfix.rdfa, cc); n = mcclellanCompile(*rdfa, cc);
} else if (outfix.haig) { } else if (auto *haig = outfix.haig()) {
// Unleash the Goughfish! // Unleash the Goughfish!
n = goughCompile(*outfix.haig, tbi.ssm.somPrecision(), cc); n = goughCompile(*haig, tbi.ssm.somPrecision(), cc);
} else if (outfix.holder) { } else if (auto *holder = outfix.holder()) {
NGHolder &h = *outfix.holder; NGHolder &h = *holder;
assert(h.kind == NFA_OUTFIX); assert(h.kind == NFA_OUTFIX);
// Build NFA. // Build NFA.
@ -1294,8 +1294,8 @@ aligned_unique_ptr<NFA> buildOutfix(RoseBuildImpl &tbi, OutfixInfo &outfix) {
} }
} }
} }
} else if (!outfix.mpv.puffettes.empty()) { } else if (auto *mpv = outfix.mpv()) {
assert(0); assert(mpv->puffettes.empty());
} }
if (n && tbi.cc.grey.reverseAccelerate) { if (n && tbi.cc.grey.reverseAccelerate) {
@ -1310,34 +1310,36 @@ void prepMpv(RoseBuildImpl &tbi, build_context &bc, size_t *historyRequired,
bool *mpv_as_outfix) { bool *mpv_as_outfix) {
assert(bc.engineOffsets.empty()); // MPV should be first assert(bc.engineOffsets.empty()); // MPV should be first
*mpv_as_outfix = false; *mpv_as_outfix = false;
OutfixInfo *mpv = nullptr; OutfixInfo *mpv_outfix = nullptr;
/* assume outfixes are just above chain tails in queue indices */ /* assume outfixes are just above chain tails in queue indices */
for (auto &out : tbi.outfixes) { for (auto &out : tbi.outfixes) {
if (out.is_nonempty_mpv()) { if (out.is_nonempty_mpv()) {
assert(!mpv); assert(!mpv_outfix);
mpv = &out; mpv_outfix = &out;
} else { } else {
assert(!out.chained); assert(!out.chained);
} }
} }
if (!mpv) { if (!mpv_outfix) {
return; return;
} }
assert(mpv->chained); assert(mpv_outfix->chained);
auto nfa = mpvCompile(mpv->mpv.puffettes, mpv->mpv.triggered_puffettes); auto *mpv = mpv_outfix->mpv();
auto nfa = mpvCompile(mpv->puffettes, mpv->triggered_puffettes);
assert(nfa); assert(nfa);
if (!nfa) { if (!nfa) {
throw CompileError("Unable to generate bytecode."); throw CompileError("Unable to generate bytecode.");
} }
if (tbi.cc.grey.reverseAccelerate) { if (tbi.cc.grey.reverseAccelerate) {
buildReverseAcceleration(nfa.get(), mpv->rev_info, mpv->minWidth); buildReverseAcceleration(nfa.get(), mpv_outfix->rev_info,
mpv_outfix->minWidth);
} }
u32 qi = mpv->get_queue(tbi.qif); u32 qi = mpv_outfix->get_queue(tbi.qif);
nfa->queueIndex = qi; nfa->queueIndex = qi;
DEBUG_PRINTF("built mpv\n"); DEBUG_PRINTF("built mpv\n");
@ -1347,7 +1349,7 @@ void prepMpv(RoseBuildImpl &tbi, build_context &bc, size_t *historyRequired,
} }
add_nfa_to_blob(bc, *nfa); add_nfa_to_blob(bc, *nfa);
*mpv_as_outfix = !mpv->mpv.puffettes.empty(); *mpv_as_outfix = !mpv->puffettes.empty();
} }
static static
@ -1387,8 +1389,7 @@ bool prepOutfixes(RoseBuildImpl &tbi, build_context &bc,
if (out.chained) { if (out.chained) {
continue; /* already done */ continue; /* already done */
} }
DEBUG_PRINTF("building outfix %zd (holder %p rdfa %p)\n", DEBUG_PRINTF("building outfix %zd\n", &out - &tbi.outfixes[0]);
&out - &tbi.outfixes[0], out.holder.get(), out.rdfa.get());
auto n = buildOutfix(tbi, out); auto n = buildOutfix(tbi, out);
if (!n) { if (!n) {
assert(0); assert(0);

View File

@ -1904,8 +1904,8 @@ bool extractSEPLiterals(const OutfixInfo &outfix, const ReportManager &rm,
// SEP cases should always become DFAs, so that's the only extract code we // SEP cases should always become DFAs, so that's the only extract code we
// have implemented here. // have implemented here.
if (outfix.rdfa) { if (outfix.rdfa()) {
return extractSEPLiterals(*outfix.rdfa, lits_out); return extractSEPLiterals(*outfix.rdfa(), lits_out);
} }
DEBUG_PRINTF("cannot extract literals from outfix type\n"); DEBUG_PRINTF("cannot extract literals from outfix type\n");

View File

@ -48,6 +48,7 @@
#include <vector> #include <vector>
#include <boost/bimap.hpp> #include <boost/bimap.hpp>
#include <boost/functional/hash/hash.hpp> #include <boost/functional/hash/hash.hpp>
#include <boost/variant.hpp>
struct RoseEngine; struct RoseEngine;
@ -302,17 +303,11 @@ struct MpvProto {
std::vector<raw_puff> triggered_puffettes; std::vector<raw_puff> triggered_puffettes;
}; };
struct OutfixInfo { /* TODO: poly */ struct OutfixInfo {
OutfixInfo() {} template<class T>
explicit OutfixInfo(std::unique_ptr<raw_dfa> r) : rdfa(std::move(r)) { explicit OutfixInfo(std::unique_ptr<T> x) : proto(std::move(x)) {}
assert(rdfa);
} explicit OutfixInfo(MpvProto mpv) : proto(std::move(mpv)) {}
explicit OutfixInfo(std::unique_ptr<NGHolder> h) : holder(std::move(h)) {
assert(holder);
}
explicit OutfixInfo(std::unique_ptr<raw_som_dfa> r) : haig(std::move(r)) {
assert(haig);
}
u32 get_queue(QueueIndexFactory &qif); u32 get_queue(QueueIndexFactory &qif);
@ -322,25 +317,68 @@ struct OutfixInfo { /* TODO: poly */
} }
bool is_nonempty_mpv() const { bool is_nonempty_mpv() const {
return !mpv.empty(); auto *mpv = boost::get<MpvProto>(&proto);
return mpv && !mpv->empty();
} }
bool is_dead() const { bool is_dead() const {
return !holder && !rdfa && !haig && mpv.empty(); auto *mpv = boost::get<MpvProto>(&proto);
if (mpv) {
return mpv->empty();
}
return boost::get<boost::blank>(&proto) != nullptr;
} }
void clear() { void clear() {
holder.reset(); proto = boost::blank();
rdfa.reset();
haig.reset();
mpv.reset();
assert(is_dead());
} }
std::unique_ptr<NGHolder> holder; // Convenience accessor functions.
std::unique_ptr<raw_dfa> rdfa;
std::unique_ptr<raw_som_dfa> haig; NGHolder *holder() {
MpvProto mpv; auto *up = boost::get<std::unique_ptr<NGHolder>>(&proto);
return up ? up->get() : nullptr;
}
raw_dfa *rdfa() {
auto *up = boost::get<std::unique_ptr<raw_dfa>>(&proto);
return up ? up->get() : nullptr;
}
raw_som_dfa *haig() {
auto *up = boost::get<std::unique_ptr<raw_som_dfa>>(&proto);
return up ? up->get() : nullptr;
}
MpvProto *mpv() {
return boost::get<MpvProto>(&proto);
}
// Convenience const accessor functions.
const NGHolder *holder() const {
auto *up = boost::get<std::unique_ptr<NGHolder>>(&proto);
return up ? up->get() : nullptr;
}
const raw_dfa *rdfa() const {
auto *up = boost::get<std::unique_ptr<raw_dfa>>(&proto);
return up ? up->get() : nullptr;
}
const raw_som_dfa *haig() const {
auto *up = boost::get<std::unique_ptr<raw_som_dfa>>(&proto);
return up ? up->get() : nullptr;
}
const MpvProto *mpv() const {
return boost::get<MpvProto>(&proto);
}
/**
* \brief Variant wrapping the various engine types. If this is
* boost::blank, it means that this outfix is unused (dead).
*/
boost::variant<
boost::blank,
std::unique_ptr<NGHolder>,
std::unique_ptr<raw_dfa>,
std::unique_ptr<raw_som_dfa>,
MpvProto> proto = boost::blank();
RevAccInfo rev_info; RevAccInfo rev_info;
u32 maxBAWidth = 0; //!< max bi-anchored width u32 maxBAWidth = 0; //!< max bi-anchored width

View File

@ -2451,8 +2451,9 @@ void mergeOutfixNfas(RoseBuildImpl &tbi, vector<NGHolder *> &nfas) {
map<NGHolder *, size_t> nfa_mapping; map<NGHolder *, size_t> nfa_mapping;
for (size_t i = 0; i < outfixes.size(); i++) { for (size_t i = 0; i < outfixes.size(); i++) {
if (outfixes[i].holder) { auto *holder = outfixes[i].holder();
nfa_mapping[outfixes[i].holder.get()] = i; if (holder) {
nfa_mapping[holder] = i;
} }
} }
@ -2485,7 +2486,7 @@ struct MergeMcClellan {
} }
static void transfer(OutfixInfo &outfix, unique_ptr<raw_dfa> d) { static void transfer(OutfixInfo &outfix, unique_ptr<raw_dfa> d) {
outfix.rdfa = move(d); outfix.proto = move(d);
} }
private: private:
@ -2503,7 +2504,7 @@ struct MergeHaig {
} }
static void transfer(OutfixInfo &outfix, unique_ptr<raw_som_dfa> d) { static void transfer(OutfixInfo &outfix, unique_ptr<raw_som_dfa> d) {
outfix.haig = move(d); outfix.proto = move(d);
} }
private: private:
@ -2602,8 +2603,9 @@ void mergeOutfixDfas(RoseBuildImpl &tbi, vector<raw_dfa *> &dfas) {
* element addition. */ * element addition. */
ue2::unordered_map<raw_dfa *, size_t> dfa_mapping; ue2::unordered_map<raw_dfa *, size_t> dfa_mapping;
for (size_t i = 0; i < outfixes.size(); i++) { for (size_t i = 0; i < outfixes.size(); i++) {
if (outfixes[i].rdfa) { auto *rdfa = outfixes[i].rdfa();
dfa_mapping[outfixes[i].rdfa.get()] = i; if (rdfa) {
dfa_mapping[rdfa] = i;
} }
} }
@ -2624,10 +2626,10 @@ void mergeOutfixCombo(RoseBuildImpl &tbi, const ReportManager &rm,
bool seen_dfa = false; bool seen_dfa = false;
u32 nfa_count = 0; u32 nfa_count = 0;
for (const auto &outfix : tbi.outfixes) { for (const auto &outfix : tbi.outfixes) {
if (outfix.holder) { if (outfix.holder()) {
DEBUG_PRINTF("nfa\n"); DEBUG_PRINTF("nfa\n");
nfa_count++; nfa_count++;
} else if (outfix.rdfa) { } else if (outfix.rdfa()) {
DEBUG_PRINTF("dfa\n"); DEBUG_PRINTF("dfa\n");
seen_dfa = true; seen_dfa = true;
} }
@ -2647,27 +2649,29 @@ void mergeOutfixCombo(RoseBuildImpl &tbi, const ReportManager &rm,
vector<raw_dfa *> dfas; vector<raw_dfa *> dfas;
for (auto it = tbi.outfixes.begin(); it != tbi.outfixes.end(); ++it) { for (auto it = tbi.outfixes.begin(); it != tbi.outfixes.end(); ++it) {
assert(!it->is_dead()); auto &outfix = *it;
assert(!it->chained); assert(!outfix.is_dead());
if (it->rdfa) { assert(!outfix.chained);
dfas.push_back(it->rdfa.get());
dfa_mapping[it->rdfa.get()] = it - tbi.outfixes.begin(); if (outfix.rdfa()) {
auto *rdfa = outfix.rdfa();
dfas.push_back(rdfa);
dfa_mapping[rdfa] = it - tbi.outfixes.begin();
continue; continue;
} }
if (!it->holder) { if (!outfix.holder()) {
continue; continue;
} }
NGHolder *h = it->holder.get(); NGHolder *h = outfix.holder();
assert(h->kind == NFA_OUTFIX); assert(h->kind == NFA_OUTFIX);
auto rdfa = buildMcClellan(*h, &rm, grey); auto rdfa = buildMcClellan(*h, &rm, grey);
if (rdfa) { if (rdfa) {
// Transform this outfix into a DFA and add it to the merge set. // Transform this outfix into a DFA and add it to the merge set.
dfa_mapping[rdfa.get()] = it - tbi.outfixes.begin(); dfa_mapping[rdfa.get()] = it - tbi.outfixes.begin();
dfas.push_back(rdfa.get()); dfas.push_back(rdfa.get());
it->clear(); outfix.proto = move(rdfa);
it->rdfa = move(rdfa);
new_dfas++; new_dfas++;
} }
} }
@ -2695,8 +2699,9 @@ void mergeOutfixHaigs(RoseBuildImpl &tbi, vector<raw_som_dfa *> &dfas,
ue2::unordered_map<raw_som_dfa *, size_t> dfa_mapping; ue2::unordered_map<raw_som_dfa *, size_t> dfa_mapping;
for (size_t i = 0; i < outfixes.size(); i++) { for (size_t i = 0; i < outfixes.size(); i++) {
if (outfixes[i].haig) { auto *haig = outfixes[i].haig();
dfa_mapping[outfixes[i].haig.get()] = i; if (haig) {
dfa_mapping[haig] = i;
} }
} }
@ -2721,14 +2726,14 @@ void mergeOutfixes(RoseBuildImpl &tbi) {
vector<raw_dfa *> dfas; vector<raw_dfa *> dfas;
vector<raw_som_dfa *> som_dfas; vector<raw_som_dfa *> som_dfas;
for (const auto &outfix : tbi.outfixes) { for (auto &outfix : tbi.outfixes) {
assert(!outfix.chained); assert(!outfix.chained);
if (outfix.rdfa) { if (outfix.rdfa()) {
dfas.push_back(outfix.rdfa.get()); dfas.push_back(outfix.rdfa());
} else if (outfix.holder) { } else if (outfix.holder()) {
nfas.push_back(outfix.holder.get()); nfas.push_back(outfix.holder());
} else if (outfix.haig) { } else if (outfix.haig()) {
som_dfas.push_back(outfix.haig.get()); som_dfas.push_back(outfix.haig());
} }
} }

View File

@ -631,10 +631,11 @@ RoseDedupeAuxImpl::RoseDedupeAuxImpl(const RoseBuildImpl &tbi_in)
} }
if (tbi.mpv_outfix) { if (tbi.mpv_outfix) {
for (const auto &puff : tbi.mpv_outfix->mpv.puffettes) { auto *mpv = tbi.mpv_outfix->mpv();
for (const auto &puff : mpv->puffettes) {
puff_map[puff.report].insert(&puff); puff_map[puff.report].insert(&puff);
} }
for (const auto &puff : tbi.mpv_outfix->mpv.triggered_puffettes) { for (const auto &puff : mpv->triggered_puffettes) {
puff_map[puff.report].insert(&puff); puff_map[puff.report].insert(&puff);
} }
} }
@ -785,12 +786,13 @@ bool RoseDedupeAuxImpl::requiresDedupeSupport(
} }
has_outfix = true; has_outfix = true;
if (out.haig) { if (out.haig()) {
return true; /* haig may report matches with different SOM at the return true; /* haig may report matches with different SOM at the
same offset */ same offset */
} }
if (out.holder && requiresDedupe(*out.holder, reports, tbi.cc.grey)) { if (out.holder() &&
requiresDedupe(*out.holder(), reports, tbi.cc.grey)) {
return true; return true;
} }
} }
@ -874,25 +876,33 @@ u32 OutfixInfo::get_queue(QueueIndexFactory &qif) {
return queue; return queue;
} }
set<ReportID> all_reports(const OutfixInfo &outfix) { namespace {
class OutfixAllReports : public boost::static_visitor<set<ReportID>> {
public:
set<ReportID> operator()(const boost::blank &) const {
return {};
}
template<class T>
set<ReportID> operator()(const unique_ptr<T> &x) const {
return all_reports(*x);
}
set<ReportID> operator()(const MpvProto &mpv) const {
set<ReportID> reports; set<ReportID> reports;
if (outfix.holder) { for (const auto &puff : mpv.puffettes) {
insert(&reports, all_reports(*outfix.holder));
}
if (outfix.rdfa) {
insert(&reports, all_reports(*outfix.rdfa));
}
if (outfix.haig) {
insert(&reports, all_reports(*outfix.haig));
}
for (const auto &puff : outfix.mpv.puffettes) {
reports.insert(puff.report); reports.insert(puff.report);
} }
for (const auto &puff : outfix.mpv.triggered_puffettes) { for (const auto &puff : mpv.triggered_puffettes) {
reports.insert(puff.report); reports.insert(puff.report);
} }
return reports;
}
};
}
set<ReportID> all_reports(const OutfixInfo &outfix) {
auto reports = boost::apply_visitor(OutfixAllReports(), outfix.proto);
assert(!reports.empty()); assert(!reports.empty());
return reports; return reports;
} }