From 76f72b6ab44e9eae387035b95833e6bf88d3d74c Mon Sep 17 00:00:00 2001 From: Justin Viiret Date: Mon, 30 Jan 2017 09:14:03 +1100 Subject: [PATCH] rose: use program offsets directly in lit tables --- src/rose/match.c | 26 +++++++-------------- src/rose/rose_build_anchored.cpp | 15 ++++++------ src/rose/rose_build_anchored.h | 5 ++-- src/rose/rose_build_bytecode.cpp | 40 ++++++++++++++++++-------------- src/rose/rose_build_impl.h | 9 ++++++- src/rose/rose_build_matchers.cpp | 24 +++++++++++-------- src/rose/rose_build_matchers.h | 26 ++++++++++----------- 7 files changed, 76 insertions(+), 69 deletions(-) diff --git a/src/rose/match.c b/src/rose/match.c index 9a702804..c7c73d25 100644 --- a/src/rose/match.c +++ b/src/rose/match.c @@ -85,19 +85,13 @@ hwlmcb_rv_t roseDelayRebuildCallback(size_t start, size_t end, u32 id, DEBUG_PRINTF("STATE groups=0x%016llx\n", tctx->groups); - const u32 *delayRebuildPrograms = - getByOffset(t, t->litDelayRebuildProgramOffset); - assert(id < t->literalCount); - const u32 program = delayRebuildPrograms[id]; - - if (program) { - const u64a som = 0; - const size_t match_len = end - start + 1; - const u8 flags = 0; - UNUSED hwlmcb_rv_t rv = roseRunProgram(t, scratch, program, som, - real_end, match_len, flags); - assert(rv != HWLM_TERMINATE_MATCHING); - } + assert(id < t->size); // id is a program offset + const u64a som = 0; + const size_t match_len = end - start + 1; + const u8 flags = 0; + UNUSED hwlmcb_rv_t rv = + roseRunProgram(t, scratch, id, som, real_end, match_len, flags); + assert(rv != HWLM_TERMINATE_MATCHING); /* we are just repopulating the delay queue, groups should be * already set from the original scan. */ @@ -245,12 +239,10 @@ hwlmcb_rv_t roseProcessMatchInline(const struct RoseEngine *t, struct hs_scratch *scratch, u64a end, size_t match_len, u32 id) { DEBUG_PRINTF("id=%u\n", id); - const u32 *programs = getByOffset(t, t->litProgramOffset); - assert(id < t->literalCount); + assert(id < t->size); // id is an offset into bytecode const u64a som = 0; const u8 flags = 0; - return roseRunProgram_i(t, scratch, programs[id], som, end, match_len, - flags); + return roseRunProgram_i(t, scratch, id, som, end, match_len, flags); } static rose_inline diff --git a/src/rose/rose_build_anchored.cpp b/src/rose/rose_build_anchored.cpp index ea565eaa..77eef142 100644 --- a/src/rose/rose_build_anchored.cpp +++ b/src/rose/rose_build_anchored.cpp @@ -208,8 +208,8 @@ void remapAnchoredReports(RoseBuildImpl &build) { * raw_dfa with program offsets. */ static -void remapIdsToPrograms(raw_dfa &rdfa, const vector &litPrograms, - const map &final_to_frag_map) { +void remapIdsToPrograms(raw_dfa &rdfa, + const map &final_to_frag_map) { for (dstate &ds : rdfa.states) { assert(ds.reports_eod.empty()); // Not used in anchored matcher. if (ds.reports.empty()) { @@ -219,9 +219,8 @@ void remapIdsToPrograms(raw_dfa &rdfa, const vector &litPrograms, flat_set new_reports; for (auto final_id : ds.reports) { assert(contains(final_to_frag_map, final_id)); - auto frag_id = final_to_frag_map.at(final_id); - assert(frag_id < litPrograms.size()); - new_reports.insert(litPrograms.at(frag_id)); + auto &frag = final_to_frag_map.at(final_id); + new_reports.insert(frag.lit_program_offset); } ds.reports = move(new_reports); } @@ -849,8 +848,8 @@ vector buildAnchoredDfas(RoseBuildImpl &build) { aligned_unique_ptr buildAnchoredMatcher(RoseBuildImpl &build, vector &dfas, - const vector &litPrograms, - const map &final_to_frag_map, size_t *asize) { + const map &final_to_frag_map, + size_t *asize) { const CompileContext &cc = build.cc; if (dfas.empty()) { @@ -860,7 +859,7 @@ buildAnchoredMatcher(RoseBuildImpl &build, vector &dfas, } for (auto &rdfa : dfas) { - remapIdsToPrograms(rdfa, litPrograms, final_to_frag_map); + remapIdsToPrograms(rdfa, final_to_frag_map); } vector> nfas; diff --git a/src/rose/rose_build_anchored.h b/src/rose/rose_build_anchored.h index fa379ff6..3d411bd7 100644 --- a/src/rose/rose_build_anchored.h +++ b/src/rose/rose_build_anchored.h @@ -30,7 +30,7 @@ #define ROSE_BUILD_ANCHORED #include "ue2common.h" -#include "rose_build.h" +#include "rose_build_impl.h" #include "nfagraph/ng_holder.h" #include "util/alloc.h" @@ -59,8 +59,7 @@ std::vector buildAnchoredDfas(RoseBuildImpl &build); */ aligned_unique_ptr buildAnchoredMatcher(RoseBuildImpl &build, std::vector &dfas, - const std::vector &litPrograms, - const std::map &final_to_frag_map, + const std::map &final_to_frag_map, size_t *asize); u32 anchoredStateSize(const anchored_matcher_info &atable); diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 321d1ca2..92e9aa59 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -213,10 +213,6 @@ struct build_context : boost::noncopyable { * that have already been pushed into the engine_blob. */ ue2::unordered_map engineOffsets; - /** \brief Literal programs, indexed by final_id, after they have been - * written to the engine_blob. */ - vector litPrograms; - /** \brief List of long literals (ones with CHECK_LONG_LIT instructions) * that need hash table support. */ vector longLiterals; @@ -4578,6 +4574,10 @@ u32 writeLiteralProgram(RoseBuildImpl &build, build_context &bc, static u32 buildDelayRebuildProgram(RoseBuildImpl &build, build_context &bc, const flat_set &final_ids) { + if (!build.cc.streaming) { + return 0; // We only do delayed rebuild in streaming mode. + } + RoseProgram program; for (const auto &final_id : final_ids) { @@ -4649,9 +4649,9 @@ rose_literal_id getFragment(const rose_literal_id &lit) { return frag; } -map groupByFragment(const RoseBuildImpl &build) { +map groupByFragment(const RoseBuildImpl &build) { u32 frag_id = 0; - map final_to_frag; + map final_to_frag; map> frag_lits; for (const auto &m : build.final_id_to_literal) { @@ -4660,21 +4660,21 @@ map groupByFragment(const RoseBuildImpl &build) { assert(!lit_ids.empty()); if (lit_ids.size() > 1) { - final_to_frag.emplace(final_id, frag_id++); + final_to_frag.emplace(final_id, LitFragment(frag_id++)); continue; } const auto lit_id = *lit_ids.begin(); const auto &lit = build.literals.right.at(lit_id); if (lit.s.length() < ROSE_SHORT_LITERAL_LEN_MAX) { - final_to_frag.emplace(final_id, frag_id++); + final_to_frag.emplace(final_id, LitFragment(frag_id++)); continue; } // Combining fragments that squash their groups is unsafe. const auto &info = build.literal_info[lit_id]; if (info.squash_group) { - final_to_frag.emplace(final_id, frag_id++); + final_to_frag.emplace(final_id, LitFragment(frag_id++)); continue; } @@ -4689,7 +4689,7 @@ map groupByFragment(const RoseBuildImpl &build) { as_string_list(m.second).c_str()); for (const auto final_id : m.second) { assert(!contains(final_to_frag, final_id)); - final_to_frag.emplace(final_id, frag_id); + final_to_frag.emplace(final_id, LitFragment(frag_id)); } frag_id++; } @@ -4709,11 +4709,11 @@ map groupByFragment(const RoseBuildImpl &build) { static tuple buildLiteralPrograms(RoseBuildImpl &build, build_context &bc, - const map &final_to_frag_map) { + map &final_to_frag_map) { // Build a reverse mapping from fragment -> final_id. map> frag_to_final_map; for (const auto &m : final_to_frag_map) { - frag_to_final_map[m.second].insert(m.first); + frag_to_final_map[m.second.fragment_id].insert(m.first); } const u32 num_fragments = verify_u32(frag_to_final_map.size()); @@ -4721,7 +4721,7 @@ buildLiteralPrograms(RoseBuildImpl &build, build_context &bc, auto lit_edge_map = findEdgesByLiteral(build); - bc.litPrograms.resize(num_fragments); + vector litPrograms(num_fragments); vector delayRebuildPrograms(num_fragments); for (u32 frag_id = 0; frag_id != num_fragments; ++frag_id) { @@ -4729,14 +4729,20 @@ buildLiteralPrograms(RoseBuildImpl &build, build_context &bc, DEBUG_PRINTF("frag_id=%u, final_ids=[%s]\n", frag_id, as_string_list(final_ids).c_str()); - bc.litPrograms[frag_id] = + litPrograms[frag_id] = writeLiteralProgram(build, bc, final_ids, lit_edge_map); delayRebuildPrograms[frag_id] = buildDelayRebuildProgram(build, bc, final_ids); } + // Update LitFragment entries. + for (auto &frag : final_to_frag_map | map_values) { + frag.lit_program_offset = litPrograms[frag.fragment_id]; + frag.delay_program_offset = delayRebuildPrograms[frag.fragment_id]; + } + u32 litProgramsOffset = - bc.engine_blob.add(begin(bc.litPrograms), end(bc.litPrograms)); + bc.engine_blob.add(begin(litPrograms), end(litPrograms)); u32 delayRebuildProgramsOffset = bc.engine_blob.add( begin(delayRebuildPrograms), end(delayRebuildPrograms)); @@ -5513,8 +5519,8 @@ aligned_unique_ptr RoseBuildImpl::buildFinalEngine(u32 minWidth) { // Build anchored matcher. size_t asize = 0; u32 amatcherOffset = 0; - auto atable = buildAnchoredMatcher(*this, anchored_dfas, bc.litPrograms, - final_to_frag_map, &asize); + auto atable = + buildAnchoredMatcher(*this, anchored_dfas, final_to_frag_map, &asize); if (atable) { currOffset = ROUNDUP_CL(currOffset); amatcherOffset = currOffset; diff --git a/src/rose/rose_build_impl.h b/src/rose/rose_build_impl.h index bfdca80c..e615d42b 100644 --- a/src/rose/rose_build_impl.h +++ b/src/rose/rose_build_impl.h @@ -642,7 +642,14 @@ void normaliseLiteralMask(const ue2_literal &s, std::vector &msk, bool canImplementGraphs(const RoseBuildImpl &tbi); #endif -std::map groupByFragment(const RoseBuildImpl &build); +struct LitFragment { + explicit LitFragment(u32 fragment_id_in) : fragment_id(fragment_id_in) {} + u32 fragment_id; + u32 lit_program_offset = 0; + u32 delay_program_offset = 0; +}; + +std::map groupByFragment(const RoseBuildImpl &build); } // namespace ue2 diff --git a/src/rose/rose_build_matchers.cpp b/src/rose/rose_build_matchers.cpp index 9f770973..c725b39d 100644 --- a/src/rose/rose_build_matchers.cpp +++ b/src/rose/rose_build_matchers.cpp @@ -637,12 +637,12 @@ u64a literalMinReportOffset(const RoseBuildImpl &build, static map makeFragGroupMap(const RoseBuildImpl &build, - const map &final_to_frag_map) { + const map &final_to_frag_map) { map frag_to_group; for (const auto &m : final_to_frag_map) { u32 final_id = m.first; - u32 frag_id = m.second; + u32 frag_id = m.second.fragment_id; hwlm_group_t groups = 0; const auto &lits = build.final_id_to_literal.at(final_id); for (auto lit_id : lits) { @@ -665,7 +665,7 @@ void trim_to_suffix(Container &c, size_t len) { } MatcherProto makeMatcherProto(const RoseBuildImpl &build, - const map &final_to_frag_map, + const map &final_to_frag_map, rose_literal_table table, bool delay_rebuild, size_t max_len, u32 max_offset) { MatcherProto mp; @@ -758,9 +758,11 @@ MatcherProto makeMatcherProto(const RoseBuildImpl &build, for (auto &lit : mp.lits) { u32 final_id = lit.id; assert(contains(final_to_frag_map, final_id)); - lit.id = final_to_frag_map.at(final_id); - assert(contains(frag_group_map, lit.id)); - lit.groups = frag_group_map.at(lit.id); + const auto &frag = final_to_frag_map.at(final_id); + lit.id = delay_rebuild ? frag.delay_program_offset + : frag.lit_program_offset; + assert(contains(frag_group_map, frag.fragment_id)); + lit.groups = frag_group_map.at(frag.fragment_id); } sort_and_unique(mp.lits); @@ -803,7 +805,7 @@ void buildAccel(const RoseBuildImpl &build, const MatcherProto &mp, aligned_unique_ptr buildFloatingMatcher(const RoseBuildImpl &build, size_t longLitLengthThreshold, - const map &final_to_frag_map, + const map &final_to_frag_map, rose_group *fgroups, size_t *fsize, size_t *historyRequired) { *fsize = 0; @@ -841,7 +843,7 @@ buildFloatingMatcher(const RoseBuildImpl &build, size_t longLitLengthThreshold, aligned_unique_ptr buildDelayRebuildMatcher( const RoseBuildImpl &build, size_t longLitLengthThreshold, - const map &final_to_frag_map, size_t *drsize) { + const map &final_to_frag_map, size_t *drsize) { *drsize = 0; if (!build.cc.streaming) { @@ -871,7 +873,8 @@ aligned_unique_ptr buildDelayRebuildMatcher( aligned_unique_ptr buildSmallBlockMatcher(const RoseBuildImpl &build, - const map &final_to_frag_map, size_t *sbsize) { + const map &final_to_frag_map, + size_t *sbsize) { *sbsize = 0; if (build.cc.streaming) { @@ -931,7 +934,8 @@ buildSmallBlockMatcher(const RoseBuildImpl &build, aligned_unique_ptr buildEodAnchoredMatcher(const RoseBuildImpl &build, - const map &final_to_frag_map, size_t *esize) { + const map &final_to_frag_map, + size_t *esize) { *esize = 0; auto mp = makeMatcherProto(build, final_to_frag_map, ROSE_EOD_ANCHORED, diff --git a/src/rose/rose_build_matchers.h b/src/rose/rose_build_matchers.h index b06d460f..d7da113c 100644 --- a/src/rose/rose_build_matchers.h +++ b/src/rose/rose_build_matchers.h @@ -67,30 +67,30 @@ struct MatcherProto { * If max_offset is specified (and not ROSE_BOUND_INF), then literals that can * only lead to a pattern match after max_offset may be excluded. */ -MatcherProto makeMatcherProto(const RoseBuildImpl &build, - const std::map &final_to_frag_map, - rose_literal_table table, bool delay_rebuild, - size_t max_len, u32 max_offset = ROSE_BOUND_INF); +MatcherProto +makeMatcherProto(const RoseBuildImpl &build, + const std::map &final_to_frag_map, + rose_literal_table table, bool delay_rebuild, size_t max_len, + u32 max_offset = ROSE_BOUND_INF); -aligned_unique_ptr buildFloatingMatcher(const RoseBuildImpl &build, - size_t longLitLengthThreshold, - const std::map &final_to_frag_map, - rose_group *fgroups, - size_t *fsize, - size_t *historyRequired); +aligned_unique_ptr +buildFloatingMatcher(const RoseBuildImpl &build, size_t longLitLengthThreshold, + const std::map &final_to_frag_map, + rose_group *fgroups, size_t *fsize, + size_t *historyRequired); aligned_unique_ptr buildDelayRebuildMatcher( const RoseBuildImpl &build, size_t longLitLengthThreshold, - const std::map &final_to_frag_map, size_t *drsize); + const std::map &final_to_frag_map, size_t *drsize); aligned_unique_ptr buildSmallBlockMatcher(const RoseBuildImpl &build, - const std::map &final_to_frag_map, + const std::map &final_to_frag_map, size_t *sbsize); aligned_unique_ptr buildEodAnchoredMatcher(const RoseBuildImpl &build, - const std::map &final_to_frag_map, + const std::map &final_to_frag_map, size_t *esize); void findMoreLiteralMasks(RoseBuildImpl &build);