diff --git a/src/nfa/accel_dfa_build_strat.cpp b/src/nfa/accel_dfa_build_strat.cpp index 019edc50..7c56ba72 100644 --- a/src/nfa/accel_dfa_build_strat.cpp +++ b/src/nfa/accel_dfa_build_strat.cpp @@ -541,17 +541,17 @@ accel_dfa_build_strat::getAccelInfo(const Grey &grey) { dstate_id_t sds_proxy = get_sds_or_proxy(rdfa); 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) { - continue; + return; } /* Note on report acceleration states: While we can't accelerate while - * we - * are spamming out callbacks, the QR code paths don't raise reports + * we are spamming out callbacks, the QR code paths don't raise reports * during scanning so they can accelerate report states. */ if (generates_callbacks(rdfa.kind) && !rdfa.states[i].reports.empty()) { - continue; + return; } size_t single_limit = @@ -562,15 +562,28 @@ accel_dfa_build_strat::getAccelInfo(const Grey &grey) { if (ei.cr.count() > single_limit) { DEBUG_PRINTF("state %zu is not accelerable has %zu\n", i, ei.cr.count()); - continue; + return; } DEBUG_PRINTF("state %zu should be accelerable %zu\n", i, ei.cr.count()); 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)) { AccelScheme sds_ei = rv[sds_proxy]; sds_ei.double_byte.clear(); /* region based on single byte scheme diff --git a/src/nfa/accel_dfa_build_strat.h b/src/nfa/accel_dfa_build_strat.h index 3cfaf272..881892ed 100644 --- a/src/nfa/accel_dfa_build_strat.h +++ b/src/nfa/accel_dfa_build_strat.h @@ -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: @@ -43,8 +43,8 @@ struct Grey; class accel_dfa_build_strat : public dfa_build_strat { public: - explicit accel_dfa_build_strat(const ReportManager &rm_in) - : dfa_build_strat(rm_in) {} + accel_dfa_build_strat(const ReportManager &rm_in, bool only_accel_init_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 size_t accelSize(void) 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, void *accel_out); virtual std::map getAccelInfo(const Grey &grey); +private: + bool only_accel_init; }; } // namespace ue2 diff --git a/src/nfa/goughcompile.cpp b/src/nfa/goughcompile.cpp index d92f285f..58b05d3d 100644 --- a/src/nfa/goughcompile.cpp +++ b/src/nfa/goughcompile.cpp @@ -80,7 +80,7 @@ public: gough_build_strat( raw_som_dfa &r, const GoughGraph &g, const ReportManager &rm_in, const map &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) {} unique_ptr gatherReports(vector &reports /* out */, vector &reports_eod /* out */, diff --git a/src/nfa/mcclellancompile.cpp b/src/nfa/mcclellancompile.cpp index 0aff6006..781a7238 100644 --- a/src/nfa/mcclellancompile.cpp +++ b/src/nfa/mcclellancompile.cpp @@ -981,8 +981,9 @@ bytecode_ptr mcclellanCompile_i(raw_dfa &raw, accel_dfa_build_strat &strat, bytecode_ptr mcclellanCompile(raw_dfa &raw, const CompileContext &cc, const ReportManager &rm, + bool only_accel_init, set *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); } diff --git a/src/nfa/mcclellancompile.h b/src/nfa/mcclellancompile.h index be0a18c5..c204e03c 100644 --- a/src/nfa/mcclellancompile.h +++ b/src/nfa/mcclellancompile.h @@ -48,8 +48,9 @@ struct CompileContext; class mcclellan_build_strat : public accel_dfa_build_strat { public: - mcclellan_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_in) - : accel_dfa_build_strat(rm_in), rdfa(rdfa_in) {} + mcclellan_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_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; } std::unique_ptr gatherReports( std::vector &reports /* out */, @@ -69,7 +70,7 @@ private: * states */ bytecode_ptr mcclellanCompile(raw_dfa &raw, const CompileContext &cc, - const ReportManager &rm, + const ReportManager &rm, bool only_accel_init, std::set *accel_states = nullptr); /* used internally by mcclellan/haig/gough compile process */ diff --git a/src/nfa/mcsheng_compile.cpp b/src/nfa/mcsheng_compile.cpp index e4e4173a..2d9658f2 100644 --- a/src/nfa/mcsheng_compile.cpp +++ b/src/nfa/mcsheng_compile.cpp @@ -1025,7 +1025,7 @@ bytecode_ptr mcshengCompile(raw_dfa &raw, const CompileContext &cc, return nullptr; } - mcclellan_build_strat mbs(raw, rm); + mcclellan_build_strat mbs(raw, rm, false); dfa_info info(mbs); bool using8bit = cc.grey.allowMcClellan8 && info.size() <= 256; diff --git a/src/nfa/shengcompile.cpp b/src/nfa/shengcompile.cpp index 8c061913..c4094ced 100644 --- a/src/nfa/shengcompile.cpp +++ b/src/nfa/shengcompile.cpp @@ -451,14 +451,14 @@ bool has_accel_sheng(const NFA *) { } bytecode_ptr shengCompile(raw_dfa &raw, const CompileContext &cc, - const ReportManager &rm, + const ReportManager &rm, bool only_accel_init, set *accel_states) { if (!cc.grey.allowSheng) { DEBUG_PRINTF("Sheng is not allowed!\n"); return nullptr; } - sheng_build_strat strat(raw, rm); + sheng_build_strat strat(raw, rm, only_accel_init); dfa_info info(strat); DEBUG_PRINTF("Trying to compile a %zu state Sheng\n", raw.states.size()); diff --git a/src/nfa/shengcompile.h b/src/nfa/shengcompile.h index 6afc1dd1..9885cd16 100644 --- a/src/nfa/shengcompile.h +++ b/src/nfa/shengcompile.h @@ -45,8 +45,9 @@ struct raw_dfa; class sheng_build_strat : public accel_dfa_build_strat { public: - sheng_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_in) - : accel_dfa_build_strat(rm_in), rdfa(rdfa_in) {} + sheng_build_strat(raw_dfa &rdfa_in, const ReportManager &rm_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; } std::unique_ptr gatherReports( std::vector &reports /* out */, @@ -63,7 +64,7 @@ private: }; bytecode_ptr shengCompile(raw_dfa &raw, const CompileContext &cc, - const ReportManager &rm, + const ReportManager &rm, bool only_accel_init, std::set *accel_states = nullptr); struct sheng_escape_info { diff --git a/src/rose/rose_build_anchored.cpp b/src/rose/rose_build_anchored.cpp index 6d56ee00..a2af160e 100644 --- a/src/rose/rose_build_anchored.cpp +++ b/src/rose/rose_build_anchored.cpp @@ -829,7 +829,7 @@ size_t buildNfas(vector &anchored_dfas, minimize_hopcroft(rdfa, cc.grey); - auto nfa = mcclellanCompile(rdfa, cc, rm); + auto nfa = mcclellanCompile(rdfa, cc, rm, false); if (!nfa) { assert(0); throw std::bad_alloc(); diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index e7b00126..1155b50a 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -720,7 +720,7 @@ bytecode_ptr getDfa(raw_dfa &rdfa, bool is_transient, const CompileContext &cc, const ReportManager &rm) { // Unleash the Sheng!! - auto dfa = shengCompile(rdfa, cc, rm); + auto dfa = shengCompile(rdfa, cc, rm, false); if (!dfa && !is_transient) { // Sheng wasn't successful, so unleash McClellan! /* We don't try the hybrid for transient prefixes due to the extra @@ -729,7 +729,7 @@ bytecode_ptr getDfa(raw_dfa &rdfa, bool is_transient, } if (!dfa) { // Sheng wasn't successful, so unleash McClellan! - dfa = mcclellanCompile(rdfa, cc, rm); + dfa = mcclellanCompile(rdfa, cc, rm, false); } return dfa; } diff --git a/src/smallwrite/smallwrite_build.cpp b/src/smallwrite/smallwrite_build.cpp index bcdd12bb..ffd3fe0f 100644 --- a/src/smallwrite/smallwrite_build.cpp +++ b/src/smallwrite/smallwrite_build.cpp @@ -692,14 +692,18 @@ bool is_slow(const raw_dfa &rdfa, const set &accel, static bytecode_ptr getDfa(raw_dfa &rdfa, const CompileContext &cc, - const ReportManager &rm, + const ReportManager &rm, bool has_literals, set &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 dfa = nullptr; if (cc.grey.allowSmallWriteSheng) { - dfa = shengCompile(rdfa, cc, rm, &accel_states); + dfa = shengCompile(rdfa, cc, rm, only_accel_init, &accel_states); } if (!dfa) { - dfa = mcclellanCompile(rdfa, cc, rm, &accel_states); + dfa = mcclellanCompile(rdfa, cc, rm, only_accel_init, &accel_states); } return dfa; } @@ -707,13 +711,14 @@ bytecode_ptr getDfa(raw_dfa &rdfa, const CompileContext &cc, static bytecode_ptr prepEngine(raw_dfa &rdfa, u32 roseQuality, 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); // Unleash the McClellan! set accel_states; - auto nfa = getDfa(rdfa, cc, rm, accel_states); + auto nfa = getDfa(rdfa, cc, rm, has_literals, accel_states); if (!nfa) { DEBUG_PRINTF("DFA compile failed for smallwrite NFA\n"); return nullptr; @@ -732,7 +737,7 @@ bytecode_ptr prepEngine(raw_dfa &rdfa, u32 roseQuality, return nullptr; } - nfa = getDfa(rdfa, cc, rm, accel_states); + nfa = getDfa(rdfa, cc, rm, has_literals, accel_states); if (!nfa) { DEBUG_PRINTF("DFA compile failed for smallwrite NFA\n"); assert(0); /* able to build orig dfa but not the trimmed? */ @@ -762,7 +767,8 @@ unique_ptr makeSmallWriteBuilder(size_t num_patterns, } bytecode_ptr 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"); poisoned = true; return nullptr; @@ -782,8 +788,8 @@ bytecode_ptr SmallWriteBuildImpl::build(u32 roseQuality) { u32 start_offset; u32 small_region; - auto nfa = - prepEngine(*rdfa, roseQuality, cc, rm, &start_offset, &small_region); + auto nfa = prepEngine(*rdfa, roseQuality, cc, rm, has_literals, + &start_offset, &small_region); if (!nfa) { DEBUG_PRINTF("some smallwrite outfix could not be prepped\n"); /* just skip the smallwrite optimization */