dfa: only accel init states from smwr path

If the small-write DFA has been built from literals, then we only need
to look for accel states at init.
This commit is contained in:
Justin Viiret 2017-04-11 10:56:22 +10:00 committed by Matthew Barr
parent 41d7aa8281
commit 0dd8536c6e
11 changed files with 57 additions and 33 deletions

View File

@ -541,17 +541,17 @@ accel_dfa_build_strat::getAccelInfo(const Grey &grey) {
dstate_id_t sds_proxy = get_sds_or_proxy(rdfa); dstate_id_t sds_proxy = get_sds_or_proxy(rdfa);
DEBUG_PRINTF("sds %hu\n", sds_proxy); DEBUG_PRINTF("sds %hu\n", sds_proxy);
for (size_t i = 0; i < rdfa.states.size(); i++) { /* Find accel info for a single state. */
auto do_state = [&](size_t i) {
if (i == DEAD_STATE) { if (i == DEAD_STATE) {
continue; return;
} }
/* Note on report acceleration states: While we can't accelerate while /* Note on report acceleration states: While we can't accelerate while
* we * we are spamming out callbacks, the QR code paths don't raise reports
* are spamming out callbacks, the QR code paths don't raise reports
* during scanning so they can accelerate report states. */ * during scanning so they can accelerate report states. */
if (generates_callbacks(rdfa.kind) && !rdfa.states[i].reports.empty()) { if (generates_callbacks(rdfa.kind) && !rdfa.states[i].reports.empty()) {
continue; return;
} }
size_t single_limit = size_t single_limit =
@ -562,15 +562,28 @@ accel_dfa_build_strat::getAccelInfo(const Grey &grey) {
if (ei.cr.count() > single_limit) { if (ei.cr.count() > single_limit) {
DEBUG_PRINTF("state %zu is not accelerable has %zu\n", i, DEBUG_PRINTF("state %zu is not accelerable has %zu\n", i,
ei.cr.count()); ei.cr.count());
continue; return;
} }
DEBUG_PRINTF("state %zu should be accelerable %zu\n", i, ei.cr.count()); DEBUG_PRINTF("state %zu should be accelerable %zu\n", i, ei.cr.count());
rv[i] = ei; rv[i] = ei;
};
if (only_accel_init) {
DEBUG_PRINTF("only computing accel for init states\n");
do_state(rdfa.start_anchored);
if (rdfa.start_floating != rdfa.start_anchored) {
do_state(rdfa.start_floating);
}
} else {
DEBUG_PRINTF("computing accel for all states\n");
for (size_t i = 0; i < rdfa.states.size(); i++) {
do_state(i);
}
} }
/* provide accleration states to states in the region of sds */ /* provide acceleration states to states in the region of sds */
if (contains(rv, sds_proxy)) { if (contains(rv, sds_proxy)) {
AccelScheme sds_ei = rv[sds_proxy]; AccelScheme sds_ei = rv[sds_proxy];
sds_ei.double_byte.clear(); /* region based on single byte scheme sds_ei.double_byte.clear(); /* region based on single byte scheme

View 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 * 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:
@ -43,8 +43,8 @@ struct Grey;
class accel_dfa_build_strat : public dfa_build_strat { class accel_dfa_build_strat : public dfa_build_strat {
public: public:
explicit accel_dfa_build_strat(const ReportManager &rm_in) accel_dfa_build_strat(const ReportManager &rm_in, bool only_accel_init_in)
: dfa_build_strat(rm_in) {} : dfa_build_strat(rm_in), only_accel_init(only_accel_init_in) {}
virtual AccelScheme find_escape_strings(dstate_id_t this_idx) const; virtual AccelScheme find_escape_strings(dstate_id_t this_idx) const;
virtual size_t accelSize(void) const = 0; virtual size_t accelSize(void) const = 0;
virtual u32 max_allowed_offset_accel() const = 0; virtual u32 max_allowed_offset_accel() const = 0;
@ -53,6 +53,8 @@ public:
virtual void buildAccel(dstate_id_t this_idx, const AccelScheme &info, virtual void buildAccel(dstate_id_t this_idx, const AccelScheme &info,
void *accel_out); void *accel_out);
virtual std::map<dstate_id_t, AccelScheme> getAccelInfo(const Grey &grey); virtual std::map<dstate_id_t, AccelScheme> getAccelInfo(const Grey &grey);
private:
bool only_accel_init;
}; };
} // namespace ue2 } // namespace ue2

View File

@ -80,7 +80,7 @@ public:
gough_build_strat( gough_build_strat(
raw_som_dfa &r, const GoughGraph &g, const ReportManager &rm_in, raw_som_dfa &r, const GoughGraph &g, const ReportManager &rm_in,
const map<dstate_id_t, gough_accel_state_info> &accel_info) const map<dstate_id_t, gough_accel_state_info> &accel_info)
: mcclellan_build_strat(r, rm_in), rdfa(r), gg(g), : mcclellan_build_strat(r, rm_in, false), rdfa(r), gg(g),
accel_gough_info(accel_info) {} accel_gough_info(accel_info) {}
unique_ptr<raw_report_info> gatherReports(vector<u32> &reports /* out */, unique_ptr<raw_report_info> gatherReports(vector<u32> &reports /* out */,
vector<u32> &reports_eod /* out */, vector<u32> &reports_eod /* out */,

View File

@ -981,8 +981,9 @@ bytecode_ptr<NFA> mcclellanCompile_i(raw_dfa &raw, accel_dfa_build_strat &strat,
bytecode_ptr<NFA> mcclellanCompile(raw_dfa &raw, const CompileContext &cc, bytecode_ptr<NFA> mcclellanCompile(raw_dfa &raw, const CompileContext &cc,
const ReportManager &rm, const ReportManager &rm,
bool only_accel_init,
set<dstate_id_t> *accel_states) { set<dstate_id_t> *accel_states) {
mcclellan_build_strat mbs(raw, rm); mcclellan_build_strat mbs(raw, rm, only_accel_init);
return mcclellanCompile_i(raw, mbs, cc, accel_states); return mcclellanCompile_i(raw, mbs, cc, accel_states);
} }

View File

@ -48,8 +48,9 @@ struct CompileContext;
class mcclellan_build_strat : public accel_dfa_build_strat { class mcclellan_build_strat : public accel_dfa_build_strat {
public: public:
mcclellan_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_in) mcclellan_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_in,
: accel_dfa_build_strat(rm_in), rdfa(rdfa_in) {} bool only_accel_init_in)
: accel_dfa_build_strat(rm_in, only_accel_init_in), rdfa(rdfa_in) {}
raw_dfa &get_raw() const override { return rdfa; } raw_dfa &get_raw() const override { return rdfa; }
std::unique_ptr<raw_report_info> gatherReports( std::unique_ptr<raw_report_info> gatherReports(
std::vector<u32> &reports /* out */, std::vector<u32> &reports /* out */,
@ -69,7 +70,7 @@ private:
* states */ * states */
bytecode_ptr<NFA> bytecode_ptr<NFA>
mcclellanCompile(raw_dfa &raw, const CompileContext &cc, mcclellanCompile(raw_dfa &raw, const CompileContext &cc,
const ReportManager &rm, const ReportManager &rm, bool only_accel_init,
std::set<dstate_id_t> *accel_states = nullptr); std::set<dstate_id_t> *accel_states = nullptr);
/* used internally by mcclellan/haig/gough compile process */ /* used internally by mcclellan/haig/gough compile process */

View File

@ -1025,7 +1025,7 @@ bytecode_ptr<NFA> mcshengCompile(raw_dfa &raw, const CompileContext &cc,
return nullptr; return nullptr;
} }
mcclellan_build_strat mbs(raw, rm); mcclellan_build_strat mbs(raw, rm, false);
dfa_info info(mbs); dfa_info info(mbs);
bool using8bit = cc.grey.allowMcClellan8 && info.size() <= 256; bool using8bit = cc.grey.allowMcClellan8 && info.size() <= 256;

View File

@ -451,14 +451,14 @@ bool has_accel_sheng(const NFA *) {
} }
bytecode_ptr<NFA> shengCompile(raw_dfa &raw, const CompileContext &cc, bytecode_ptr<NFA> shengCompile(raw_dfa &raw, const CompileContext &cc,
const ReportManager &rm, const ReportManager &rm, bool only_accel_init,
set<dstate_id_t> *accel_states) { set<dstate_id_t> *accel_states) {
if (!cc.grey.allowSheng) { if (!cc.grey.allowSheng) {
DEBUG_PRINTF("Sheng is not allowed!\n"); DEBUG_PRINTF("Sheng is not allowed!\n");
return nullptr; return nullptr;
} }
sheng_build_strat strat(raw, rm); sheng_build_strat strat(raw, rm, only_accel_init);
dfa_info info(strat); dfa_info info(strat);
DEBUG_PRINTF("Trying to compile a %zu state Sheng\n", raw.states.size()); DEBUG_PRINTF("Trying to compile a %zu state Sheng\n", raw.states.size());

View File

@ -45,8 +45,9 @@ struct raw_dfa;
class sheng_build_strat : public accel_dfa_build_strat { class sheng_build_strat : public accel_dfa_build_strat {
public: public:
sheng_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_in) sheng_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_in,
: accel_dfa_build_strat(rm_in), rdfa(rdfa_in) {} bool only_accel_init_in)
: accel_dfa_build_strat(rm_in, only_accel_init_in), rdfa(rdfa_in) {}
raw_dfa &get_raw() const override { return rdfa; } raw_dfa &get_raw() const override { return rdfa; }
std::unique_ptr<raw_report_info> gatherReports( std::unique_ptr<raw_report_info> gatherReports(
std::vector<u32> &reports /* out */, std::vector<u32> &reports /* out */,
@ -63,7 +64,7 @@ private:
}; };
bytecode_ptr<NFA> shengCompile(raw_dfa &raw, const CompileContext &cc, bytecode_ptr<NFA> shengCompile(raw_dfa &raw, const CompileContext &cc,
const ReportManager &rm, const ReportManager &rm, bool only_accel_init,
std::set<dstate_id_t> *accel_states = nullptr); std::set<dstate_id_t> *accel_states = nullptr);
struct sheng_escape_info { struct sheng_escape_info {

View File

@ -829,7 +829,7 @@ size_t buildNfas(vector<raw_dfa> &anchored_dfas,
minimize_hopcroft(rdfa, cc.grey); minimize_hopcroft(rdfa, cc.grey);
auto nfa = mcclellanCompile(rdfa, cc, rm); auto nfa = mcclellanCompile(rdfa, cc, rm, false);
if (!nfa) { if (!nfa) {
assert(0); assert(0);
throw std::bad_alloc(); throw std::bad_alloc();

View File

@ -720,7 +720,7 @@ bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, bool is_transient,
const CompileContext &cc, const CompileContext &cc,
const ReportManager &rm) { const ReportManager &rm) {
// Unleash the Sheng!! // Unleash the Sheng!!
auto dfa = shengCompile(rdfa, cc, rm); auto dfa = shengCompile(rdfa, cc, rm, false);
if (!dfa && !is_transient) { if (!dfa && !is_transient) {
// Sheng wasn't successful, so unleash McClellan! // Sheng wasn't successful, so unleash McClellan!
/* We don't try the hybrid for transient prefixes due to the extra /* We don't try the hybrid for transient prefixes due to the extra
@ -729,7 +729,7 @@ bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, bool is_transient,
} }
if (!dfa) { if (!dfa) {
// Sheng wasn't successful, so unleash McClellan! // Sheng wasn't successful, so unleash McClellan!
dfa = mcclellanCompile(rdfa, cc, rm); dfa = mcclellanCompile(rdfa, cc, rm, false);
} }
return dfa; return dfa;
} }

View File

@ -692,14 +692,18 @@ bool is_slow(const raw_dfa &rdfa, const set<dstate_id_t> &accel,
static static
bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, const CompileContext &cc, bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, const CompileContext &cc,
const ReportManager &rm, const ReportManager &rm, bool has_literals,
set<dstate_id_t> &accel_states) { set<dstate_id_t> &accel_states) {
// If we determinised literals, then we only need to consider the init
// states for acceleration.
bool only_accel_init = has_literals;
bytecode_ptr<NFA> dfa = nullptr; bytecode_ptr<NFA> dfa = nullptr;
if (cc.grey.allowSmallWriteSheng) { if (cc.grey.allowSmallWriteSheng) {
dfa = shengCompile(rdfa, cc, rm, &accel_states); dfa = shengCompile(rdfa, cc, rm, only_accel_init, &accel_states);
} }
if (!dfa) { if (!dfa) {
dfa = mcclellanCompile(rdfa, cc, rm, &accel_states); dfa = mcclellanCompile(rdfa, cc, rm, only_accel_init, &accel_states);
} }
return dfa; return dfa;
} }
@ -707,13 +711,14 @@ bytecode_ptr<NFA> getDfa(raw_dfa &rdfa, const CompileContext &cc,
static static
bytecode_ptr<NFA> prepEngine(raw_dfa &rdfa, u32 roseQuality, bytecode_ptr<NFA> prepEngine(raw_dfa &rdfa, u32 roseQuality,
const CompileContext &cc, const ReportManager &rm, const CompileContext &cc, const ReportManager &rm,
u32 *start_offset, u32 *small_region) { bool has_literals, u32 *start_offset,
u32 *small_region) {
*start_offset = remove_leading_dots(rdfa); *start_offset = remove_leading_dots(rdfa);
// Unleash the McClellan! // Unleash the McClellan!
set<dstate_id_t> accel_states; set<dstate_id_t> accel_states;
auto nfa = getDfa(rdfa, cc, rm, accel_states); auto nfa = getDfa(rdfa, cc, rm, has_literals, accel_states);
if (!nfa) { if (!nfa) {
DEBUG_PRINTF("DFA compile failed for smallwrite NFA\n"); DEBUG_PRINTF("DFA compile failed for smallwrite NFA\n");
return nullptr; return nullptr;
@ -732,7 +737,7 @@ bytecode_ptr<NFA> prepEngine(raw_dfa &rdfa, u32 roseQuality,
return nullptr; return nullptr;
} }
nfa = getDfa(rdfa, cc, rm, accel_states); nfa = getDfa(rdfa, cc, rm, has_literals, accel_states);
if (!nfa) { if (!nfa) {
DEBUG_PRINTF("DFA compile failed for smallwrite NFA\n"); DEBUG_PRINTF("DFA compile failed for smallwrite NFA\n");
assert(0); /* able to build orig dfa but not the trimmed? */ assert(0); /* able to build orig dfa but not the trimmed? */
@ -762,7 +767,8 @@ unique_ptr<SmallWriteBuild> makeSmallWriteBuilder(size_t num_patterns,
} }
bytecode_ptr<SmallWriteEngine> SmallWriteBuildImpl::build(u32 roseQuality) { bytecode_ptr<SmallWriteEngine> SmallWriteBuildImpl::build(u32 roseQuality) {
if (!rdfa && is_empty(lit_trie) && is_empty(lit_trie_nocase)) { const bool has_literals = !is_empty(lit_trie) || !is_empty(lit_trie_nocase);
if (!rdfa && !has_literals) {
DEBUG_PRINTF("no smallwrite engine\n"); DEBUG_PRINTF("no smallwrite engine\n");
poisoned = true; poisoned = true;
return nullptr; return nullptr;
@ -782,8 +788,8 @@ bytecode_ptr<SmallWriteEngine> SmallWriteBuildImpl::build(u32 roseQuality) {
u32 start_offset; u32 start_offset;
u32 small_region; u32 small_region;
auto nfa = auto nfa = prepEngine(*rdfa, roseQuality, cc, rm, has_literals,
prepEngine(*rdfa, roseQuality, cc, rm, &start_offset, &small_region); &start_offset, &small_region);
if (!nfa) { if (!nfa) {
DEBUG_PRINTF("some smallwrite outfix could not be prepped\n"); DEBUG_PRINTF("some smallwrite outfix could not be prepped\n");
/* just skip the smallwrite optimization */ /* just skip the smallwrite optimization */