/** \brief mapping from suffix to queue index. */
map<suffix_id, u32> suffixes;
- /** \brief Number of roles with a state bit.
- *
- * This is set by assignStateIndices() and should be constant throughout
- * the rest of the compile.
- */
- size_t numStates = 0;
-
/** \brief Simple cache of programs written to engine blob, used for
* deduplication. */
ue2::unordered_map<RoseProgram, u32, RoseProgramHash,
* and reach table size. */
size_t reachTableSize = 0;
- /** \brief State indices, for those roles that have them. */
- ue2::unordered_map<RoseVertex, u32> roleStateIndices;
+ /** \brief State indices, for those roles that have them.
+ * Each vertex present has a unique state index in the range
+ * [0, roleStateIndices.size()). */
+ unordered_map<RoseVertex, u32> roleStateIndices;
/** \brief Mapping from queue index to bytecode offset for built engines
* that have already been pushed into the engine_blob. */
* that need hash table support. */
vector<ue2_case_string> longLiterals;
- /** \brief Minimum offset of a match from the floating table. */
- u32 floatingMinLiteralMatchOffset = 0;
-
/** \brief Long literal length threshold, used in streaming mode. */
size_t longLitLengthThreshold = 0;
/** \brief Data only used during construction of various programs (literal,
* anchored, delay, etc). */
struct ProgramBuild : noncopyable {
+ explicit ProgramBuild(u32 fMinLitOffset)
+ : floatingMinLiteralMatchOffset(fMinLitOffset) {
+ }
+
+ /** \brief Minimum offset of a match from the floating table. */
+ const u32 floatingMinLiteralMatchOffset;
+
/** \brief Mapping from vertex to key, for vertices with a
* CHECK_NOT_HANDLED instruction. */
ue2::unordered_map<RoseVertex, u32> handledKeys;
}
static
-u8 pickRuntimeImpl(const RoseBuildImpl &build, const build_context &bc,
+u8 pickRuntimeImpl(const RoseBuildImpl &build, const RoseResources &resources,
UNUSED u32 outfixEndQueue) {
- DEBUG_PRINTF("has_outfixes=%d\n", bc.resources.has_outfixes);
- DEBUG_PRINTF("has_suffixes=%d\n", bc.resources.has_suffixes);
- DEBUG_PRINTF("has_leftfixes=%d\n", bc.resources.has_leftfixes);
- DEBUG_PRINTF("has_literals=%d\n", bc.resources.has_literals);
- DEBUG_PRINTF("has_states=%d\n", bc.resources.has_states);
- DEBUG_PRINTF("checks_groups=%d\n", bc.resources.checks_groups);
- DEBUG_PRINTF("has_lit_delay=%d\n", bc.resources.has_lit_delay);
- DEBUG_PRINTF("has_lit_check=%d\n", bc.resources.has_lit_check);
- DEBUG_PRINTF("has_anchored=%d\n", bc.resources.has_anchored);
- DEBUG_PRINTF("has_floating=%d\n", bc.resources.has_floating);
- DEBUG_PRINTF("has_eod=%d\n", bc.resources.has_eod);
-
- if (isPureFloating(bc.resources, build.cc)) {
+ DEBUG_PRINTF("has_outfixes=%d\n", resources.has_outfixes);
+ DEBUG_PRINTF("has_suffixes=%d\n", resources.has_suffixes);
+ DEBUG_PRINTF("has_leftfixes=%d\n", resources.has_leftfixes);
+ DEBUG_PRINTF("has_literals=%d\n", resources.has_literals);
+ DEBUG_PRINTF("has_states=%d\n", resources.has_states);
+ DEBUG_PRINTF("checks_groups=%d\n", resources.checks_groups);
+ DEBUG_PRINTF("has_lit_delay=%d\n", resources.has_lit_delay);
+ DEBUG_PRINTF("has_lit_check=%d\n", resources.has_lit_check);
+ DEBUG_PRINTF("has_anchored=%d\n", resources.has_anchored);
+ DEBUG_PRINTF("has_floating=%d\n", resources.has_floating);
+ DEBUG_PRINTF("has_eod=%d\n", resources.has_eod);
+
+ if (isPureFloating(resources, build.cc)) {
return ROSE_RUNTIME_PURE_LITERAL;
}
setLeftNfaProperties(*nfa, leftfix);
- build.leftfix_queue_map.emplace(leftfix, qi);
nfa->queueIndex = qi;
if (!prefix && !leftfix.haig() && leftfix.graph()
static
void updateExclusiveInfixProperties(const RoseBuildImpl &build,
- build_context &bc,
- const vector<ExclusiveInfo> &exclusive_info,
- set<u32> *no_retrigger_queues) {
+ const vector<ExclusiveInfo> &exclusive_info,
+ map<RoseVertex, left_build_info> &leftfix_info,
+ set<u32> *no_retrigger_queues) {
const RoseGraph &g = build.g;
for (const auto &info : exclusive_info) {
// Set leftfix optimisations, disabled for tamarama subengines
const auto &verts = sub.vertices;
for (const auto &v : verts) {
u32 lag = g[v].left.lag;
- bc.leftfix_info.emplace(
- v, left_build_info(qi, lag, max_width, squash_mask, stop,
- max_queuelen, cm_count, cm_cr));
+ leftfix_info.emplace(v, left_build_info(qi, lag, max_width,
+ squash_mask, stop,
+ max_queuelen, cm_count,
+ cm_cr));
}
}
}
info.queue = qif.get_queue();
exclusive_info.push_back(move(info));
}
- updateExclusiveInfixProperties(build, bc, exclusive_info,
+ updateExclusiveInfixProperties(build, exclusive_info, bc.leftfix_info,
no_retrigger_queues);
buildInfixContainer(g, bc, exclusive_info);
}
}
static
-void assignSuffixQueues(RoseBuildImpl &build, build_context &bc) {
+void assignSuffixQueues(RoseBuildImpl &build, map<suffix_id, u32> &suffixes) {
const RoseGraph &g = build.g;
for (auto v : vertices_range(g)) {
DEBUG_PRINTF("vertex %zu triggers suffix %p\n", g[v].index, s.graph());
// We may have already built this NFA.
- if (contains(bc.suffixes, s)) {
+ if (contains(suffixes, s)) {
continue;
}
u32 queue = build.qif.get_queue();
DEBUG_PRINTF("assigning %p to queue %u\n", s.graph(), queue);
- bc.suffixes.emplace(s, queue);
- build.suffix_queue_map.emplace(s, queue);
+ suffixes.emplace(s, queue);
}
}
no_retrigger_queues);
}
- assignSuffixQueues(tbi, bc);
+ assignSuffixQueues(tbi, bc.suffixes);
if (!buildSuffixes(tbi, bc, no_retrigger_queues, suffixTriggers)) {
return false;
return 0; /* invalid offset */
}
- vector<mmbit_sparse_iter> iter;
- mmbBuildSparseIterator(iter, lb_roles, bc.numStates);
+ auto iter = mmbBuildSparseIterator(lb_roles, bc.roleStateIndices.size());
return bc.engine_blob.add_iterator(iter);
}
DEBUG_PRINTF("building iter for %zu nfas\n", keys.size());
- vector<mmbit_sparse_iter> iter;
- mmbBuildSparseIterator(iter, keys, activeQueueCount);
+ auto iter = mmbBuildSparseIterator(keys, activeQueueCount);
return bc.engine_blob.add_iterator(iter);
}
static
void recordResources(RoseResources &resources,
- const RoseBuildImpl &build) {
+ const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments) {
if (!build.outfixes.empty()) {
resources.has_outfixes = true;
}
- resources.has_literals =
- any_of(begin(build.literal_info), end(build.literal_info),
- [](const rose_literal_info &info) {
- return info.fragment_id != MO_INVALID_IDX;
- });
+ resources.has_literals = !fragments.empty();
const auto &g = build.g;
for (const auto &v : vertices_range(g)) {
}
static
-void recordLongLiterals(build_context &bc, const RoseProgram &program) {
+void recordLongLiterals(vector<ue2_case_string> &longLiterals,
+ const RoseProgram &program) {
for (const auto &ri : program) {
if (const auto *ri_check =
dynamic_cast<const RoseInstrCheckLongLit *>(ri.get())) {
DEBUG_PRINTF("found CHECK_LONG_LIT for string '%s'\n",
escapeString(ri_check->literal).c_str());
- bc.longLiterals.emplace_back(ri_check->literal, false);
+ longLiterals.emplace_back(ri_check->literal, false);
continue;
}
if (const auto *ri_check =
dynamic_cast<const RoseInstrCheckLongLitNocase *>(ri.get())) {
DEBUG_PRINTF("found CHECK_LONG_LIT_NOCASE for string '%s'\n",
escapeString(ri_check->literal).c_str());
- bc.longLiterals.emplace_back(ri_check->literal, true);
+ longLiterals.emplace_back(ri_check->literal, true);
}
}
}
}
recordResources(bc.resources, program);
- recordLongLiterals(bc, program);
+ recordLongLiterals(bc.longLiterals, program);
u32 len = 0;
auto prog_bytecode = writeProgram(bc.engine_blob, program, &len);
}
static
-u32 writeActiveLeftIter(build_context &bc,
+u32 writeActiveLeftIter(RoseEngineBlob &engine_blob,
const vector<LeftNfaInfo> &leftInfoTable) {
vector<u32> keys;
for (size_t i = 0; i < leftInfoTable.size(); i++) {
return 0;
}
- vector<mmbit_sparse_iter> iter;
- mmbBuildSparseIterator(iter, keys, verify_u32(leftInfoTable.size()));
- return bc.engine_blob.add_iterator(iter);
+ auto iter = mmbBuildSparseIterator(keys, verify_u32(leftInfoTable.size()));
+ return engine_blob.add_iterator(iter);
}
static
}
static
-void writeDkeyInfo(const ReportManager &rm, build_context &bc,
+void writeDkeyInfo(const ReportManager &rm, RoseEngineBlob &engine_blob,
RoseEngine &proto) {
const auto inv_dkeys = rm.getDkeyToReportTable();
- proto.invDkeyOffset = bc.engine_blob.add_range(inv_dkeys);
+ proto.invDkeyOffset = engine_blob.add_range(inv_dkeys);
proto.dkeyCount = rm.numDkeys();
proto.dkeyLogSize = fatbit_size(proto.dkeyCount);
}
static
-void writeLeftInfo(build_context &bc, RoseEngine &proto,
+void writeLeftInfo(RoseEngineBlob &engine_blob, RoseEngine &proto,
const vector<LeftNfaInfo> &leftInfoTable) {
- proto.leftOffset = bc.engine_blob.add_range(leftInfoTable);
- proto.activeLeftIterOffset = writeActiveLeftIter(bc, leftInfoTable);
+ proto.leftOffset = engine_blob.add_range(leftInfoTable);
+ proto.activeLeftIterOffset
+ = writeActiveLeftIter(engine_blob, leftInfoTable);
proto.roseCount = verify_u32(leftInfoTable.size());
proto.activeLeftCount = verify_u32(leftInfoTable.size());
proto.rosePrefixCount = countRosePrefixes(leftInfoTable);
}
static
-void makeRoleCheckLeftfix(const RoseBuildImpl &build, build_context &bc,
+void makeRoleCheckLeftfix(const RoseBuildImpl &build,
+ const map<RoseVertex, left_build_info> &leftfix_info,
RoseVertex v, RoseProgram &program) {
- auto it = bc.leftfix_info.find(v);
- if (it == end(bc.leftfix_info)) {
+ auto it = leftfix_info.find(v);
+ if (it == end(leftfix_info)) {
return;
}
const left_build_info &lni = it->second;
}
static
-void makeRoleAnchoredDelay(const RoseBuildImpl &build, build_context &bc,
+void makeRoleAnchoredDelay(const RoseBuildImpl &build,
+ u32 floatingMinLiteralMatchOffset,
RoseVertex v, RoseProgram &program) {
// Only relevant for roles that can be triggered by the anchored table.
if (!build.isAnchored(v)) {
// If this match cannot occur after floatingMinLiteralMatchOffset, we do
// not need this check.
- if (build.g[v].max_offset <= bc.floatingMinLiteralMatchOffset) {
+ if (build.g[v].max_offset <= floatingMinLiteralMatchOffset) {
return;
}
}
static
-void makeCatchup(const RoseBuildImpl &build, const build_context &bc,
+void makeCatchup(const RoseBuildImpl &build, bool needs_catchup,
const flat_set<ReportID> &reports, RoseProgram &program) {
- if (!bc.needs_catchup) {
+ if (!needs_catchup) {
return;
}
}
static
-void makeCatchupMpv(const RoseBuildImpl &build, const build_context &bc,
+void makeCatchupMpv(const RoseBuildImpl &build, bool needs_mpv_catchup,
ReportID id, RoseProgram &program) {
- if (!bc.needs_mpv_catchup) {
+ if (!needs_mpv_catchup) {
return;
}
}
const auto &reports = g[v].reports;
- makeCatchup(build, bc, reports, program);
+ makeCatchup(build, bc.needs_catchup, reports, program);
RoseProgram report_block;
for (ReportID id : reports) {
}
static
-void makeRoleSetState(const build_context &bc, RoseVertex v,
- RoseProgram &program) {
+void makeRoleSetState(const unordered_map<RoseVertex, u32> &roleStateIndices,
+ RoseVertex v, RoseProgram &program) {
// We only need this instruction if a state index has been assigned to this
// vertex.
- auto it = bc.roleStateIndices.find(v);
- if (it == end(bc.roleStateIndices)) {
+ auto it = roleStateIndices.find(v);
+ if (it == end(roleStateIndices)) {
return;
}
program.add_before_end(make_unique<RoseInstrSetState>(it->second));
// First, add program instructions that enforce preconditions without
// effects.
- makeRoleAnchoredDelay(build, bc, v, program);
+ makeRoleAnchoredDelay(build, prog_build.floatingMinLiteralMatchOffset, v,
+ program);
if (onlyAtEod(build, v)) {
DEBUG_PRINTF("only at eod\n");
}
makeRoleLookaround(build, bc, v, program);
- makeRoleCheckLeftfix(build, bc, v, program);
+ makeRoleCheckLeftfix(build, bc.leftfix_info, v, program);
// Next, we can add program instructions that have effects. This must be
// done as a series of blocks, as some of them (like reports) are
effects_block.add_block(move(suffix_block));
RoseProgram state_block;
- makeRoleSetState(bc, v, state_block);
+ makeRoleSetState(bc.roleStateIndices, v, state_block);
effects_block.add_block(move(state_block));
// Note: EOD eager reports may generate a CHECK_ONLY_EOD instruction (if
}
static
-void assignStateIndices(const RoseBuildImpl &build, build_context &bc) {
+unordered_map<RoseVertex, u32> assignStateIndices(const RoseBuildImpl &build) {
const auto &g = build.g;
u32 state = 0;
-
+ unordered_map<RoseVertex, u32> roleStateIndices;
for (auto v : vertices_range(g)) {
// Virtual vertices (starts, EOD accept vertices) never need state
// indices.
}
/* TODO: also don't need a state index if all edges are nfa based */
- bc.roleStateIndices.emplace(v, state++);
+ roleStateIndices.emplace(v, state++);
}
DEBUG_PRINTF("assigned %u states (from %zu vertices)\n", state,
num_vertices(g));
- bc.numStates = state;
+
+ return roleStateIndices;
}
static
}
static
-void addPredBlocksAny(const build_context &bc,
- map<u32, RoseProgram> &pred_blocks,
+void addPredBlocksAny(map<u32, RoseProgram> &pred_blocks, u32 num_states,
RoseProgram &program) {
RoseProgram sparse_program;
}
const RoseInstruction *end_inst = sparse_program.end_instruction();
- auto ri = make_unique<RoseInstrSparseIterAny>(bc.numStates, keys, end_inst);
+ auto ri = make_unique<RoseInstrSparseIterAny>(num_states, keys, end_inst);
sparse_program.add_before_end(move(ri));
RoseProgram &block = pred_blocks.begin()->second;
}
static
-void addPredBlocksMulti(const build_context &bc,
- map<u32, RoseProgram> &pred_blocks,
- RoseProgram &program) {
+void addPredBlocksMulti(map<u32, RoseProgram> &pred_blocks,
+ u32 num_states, RoseProgram &program) {
assert(!pred_blocks.empty());
RoseProgram sparse_program;
vector<pair<u32, const RoseInstruction *>> jump_table;
// BEGIN instruction.
- auto ri_begin =
- make_unique<RoseInstrSparseIterBegin>(bc.numStates, end_inst);
+ auto ri_begin = make_unique<RoseInstrSparseIterBegin>(num_states, end_inst);
RoseInstrSparseIterBegin *begin_inst = ri_begin.get();
sparse_program.add_before_end(move(ri_begin));
}
static
-void addPredBlocks(const build_context &bc, map<u32, RoseProgram> &pred_blocks,
+void addPredBlocks(map<u32, RoseProgram> &pred_blocks, u32 num_states,
RoseProgram &program) {
// Trim empty blocks, if any exist.
for (auto it = pred_blocks.begin(); it != pred_blocks.end();) {
return RoseProgramEquivalence()(*begin(blocks), block);
})) {
DEBUG_PRINTF("all blocks equiv\n");
- addPredBlocksAny(bc, pred_blocks, program);
+ addPredBlocksAny(pred_blocks, num_states, program);
return;
}
- addPredBlocksMulti(bc, pred_blocks, program);
+ addPredBlocksMulti(pred_blocks, num_states, program);
}
static
}
static
-void makeCheckLitEarlyInstruction(const RoseBuildImpl &build, build_context &bc,
- u32 lit_id, const vector<RoseEdge> &lit_edges,
+void makeCheckLitEarlyInstruction(const RoseBuildImpl &build, u32 lit_id,
+ const vector<RoseEdge> &lit_edges,
+ u32 floatingMinLiteralMatchOffset,
RoseProgram &program) {
if (lit_edges.empty()) {
return;
}
- if (bc.floatingMinLiteralMatchOffset == 0) {
+ if (floatingMinLiteralMatchOffset == 0) {
return;
}
const auto &lit = build.literals.right.at(lit_id);
size_t min_len = lit.elength();
u32 min_offset = findMinOffset(build, lit_id);
- DEBUG_PRINTF("has min_len=%zu, min_offset=%u, "
- "global min is %u\n", min_len, min_offset,
- bc.floatingMinLiteralMatchOffset);
+ DEBUG_PRINTF("has min_len=%zu, min_offset=%u, global min is %u\n", min_len,
+ min_offset, floatingMinLiteralMatchOffset);
// If we can't match before the min offset, we don't need the check.
- if (min_len >= bc.floatingMinLiteralMatchOffset) {
+ if (min_len >= floatingMinLiteralMatchOffset) {
DEBUG_PRINTF("no need for check, min is %u\n",
- bc.floatingMinLiteralMatchOffset);
+ floatingMinLiteralMatchOffset);
return;
}
- assert(min_offset >= bc.floatingMinLiteralMatchOffset);
+ assert(min_offset >= floatingMinLiteralMatchOffset);
assert(min_offset < UINT32_MAX);
DEBUG_PRINTF("adding lit early check, min_offset=%u\n", min_offset);
}
static
-void makeCheckLiteralInstruction(const RoseBuildImpl &build,
- const build_context &bc, u32 lit_id,
+void makeCheckLiteralInstruction(const RoseBuildImpl &build, u32 lit_id,
+ size_t longLitLengthThreshold,
RoseProgram &program) {
- assert(bc.longLitLengthThreshold > 0);
+ assert(longLitLengthThreshold > 0);
DEBUG_PRINTF("lit_id=%u, long lit threshold %zu\n", lit_id,
- bc.longLitLengthThreshold);
+ longLitLengthThreshold);
if (build.isDelayed(lit_id)) {
return;
throw ResourceLimitError();
}
- if (lit.s.length() <= bc.longLitLengthThreshold) {
+ if (lit.s.length() <= longLitLengthThreshold) {
DEBUG_PRINTF("is a medium-length literal\n");
const auto *end_inst = program.end_instruction();
unique_ptr<RoseInstruction> ri;
RoseProgram program;
// Check long literal info.
- makeCheckLiteralInstruction(build, bc, lit_id, program);
+ makeCheckLiteralInstruction(build, lit_id, bc.longLitLengthThreshold,
+ program);
// Check lit mask.
makeCheckLitMaskInstruction(build, bc, lit_id, program);
makePushDelayedInstructions(build, prog_build, lit_id, program);
// Add pre-check for early literals in the floating table.
- makeCheckLitEarlyInstruction(build, bc, lit_id, lit_edges, program);
+ makeCheckLitEarlyInstruction(build, lit_id, lit_edges,
+ prog_build.floatingMinLiteralMatchOffset,
+ program);
return program;
}
// Add blocks to deal with non-root edges (triggered by sparse iterator or
// mmbit_isset checks).
- addPredBlocks(bc, pred_blocks, program);
+ addPredBlocks(pred_blocks, bc.roleStateIndices.size(), program);
// Add blocks to handle root roles.
for (const auto &e : lit_edges) {
static
u32 writeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
- ProgramBuild &prog_build, const flat_set<u32> &lit_ids,
+ ProgramBuild &prog_build, const vector<u32> &lit_ids,
const map<u32, vector<RoseEdge>> &lit_edge_map,
bool is_anchored_program) {
assert(!lit_ids.empty());
static
u32 writeDelayRebuildProgram(const RoseBuildImpl &build, build_context &bc,
ProgramBuild &prog_build,
- const flat_set<u32> &lit_ids) {
+ const vector<u32> &lit_ids) {
assert(!lit_ids.empty());
if (!build.cc.streaming) {
}
RoseProgram prog;
- makeCheckLiteralInstruction(build, bc, lit_id, prog);
+ makeCheckLiteralInstruction(build, lit_id, bc.longLitLengthThreshold,
+ prog);
makeCheckLitMaskInstruction(build, bc, lit_id, prog);
makePushDelayedInstructions(build, prog_build, lit_id, prog);
blocks.push_back(move(prog));
}
static
-void groupByFragment(RoseBuildImpl &build) {
+vector<LitFragment> groupByFragment(const RoseBuildImpl &build) {
+ vector<LitFragment> fragments;
u32 frag_id = 0;
struct FragmentInfo {
};
map<rose_literal_id, FragmentInfo> frag_info;
- map<u32, u32> lit_to_frag;
-
- auto &fragments = build.fragments;
for (const auto &m : build.literals.right) {
const u32 lit_id = m.first;
auto groups = info.group_mask;
if (lit.s.length() < ROSE_SHORT_LITERAL_LEN_MAX) {
- lit_to_frag.emplace(lit_id, frag_id);
- fragments.emplace_back(frag_id, groups);
+ fragments.emplace_back(frag_id, groups, lit_id);
frag_id++;
continue;
}
fi.groups |= groups;
}
- for (const auto &m : frag_info) {
- const auto &fi = m.second;
+ for (auto &m : frag_info) {
+ auto &fi = m.second;
DEBUG_PRINTF("frag %s -> ids: %s\n", dumpString(m.first.s).c_str(),
as_string_list(fi.lit_ids).c_str());
- fragments.emplace_back(frag_id, fi.groups);
- for (const auto lit_id : fi.lit_ids) {
- assert(!contains(lit_to_frag, lit_id));
- lit_to_frag.emplace(lit_id, frag_id);
- }
+ sort(fi.lit_ids.begin(), fi.lit_ids.end()); /* to match old behaviour */
+ fragments.emplace_back(frag_id, fi.groups, move(fi.lit_ids));
frag_id++;
+ assert(frag_id == fragments.size());
}
- // Write the fragment IDs into the literal_info structures.
- for (const auto &m : lit_to_frag) {
- build.literal_info[m.first].fragment_id = m.second;
- }
+ return fragments;
}
/**
* \brief Build the interpreter programs for each literal.
*/
static
-void buildLiteralPrograms(RoseBuildImpl &build, build_context &bc,
+void buildLiteralPrograms(const RoseBuildImpl &build,
+ vector<LitFragment> &fragments, build_context &bc,
ProgramBuild &prog_build) {
- // Build a reverse mapping from fragment -> {lit_id, lit_id,...}
- map<u32, flat_set<u32>> frag_to_lit_map;
- for (u32 lit_id = 0; lit_id < verify_u32(build.literal_info.size());
- lit_id++) {
- const auto &info = build.literal_info[lit_id];
- if (info.fragment_id == MO_INVALID_IDX) {
- continue;
- }
- frag_to_lit_map[info.fragment_id].insert(lit_id);
- }
-
- DEBUG_PRINTF("%zu fragments\n", build.fragments.size());
+ DEBUG_PRINTF("%zu fragments\n", fragments.size());
auto lit_edge_map = findEdgesByLiteral(build);
- for (auto &frag : build.fragments) {
- const auto &lit_ids = frag_to_lit_map[frag.fragment_id];
+ for (auto &frag : fragments) {
DEBUG_PRINTF("frag_id=%u, lit_ids=[%s]\n", frag.fragment_id,
- as_string_list(lit_ids).c_str());
+ as_string_list(frag.lit_ids).c_str());
- frag.lit_program_offset = writeLiteralProgram(
- build, bc, prog_build, lit_ids, lit_edge_map, false);
- frag.delay_program_offset =
- writeDelayRebuildProgram(build, bc, prog_build, lit_ids);
+ frag.lit_program_offset
+ = writeLiteralProgram(build, bc, prog_build, frag.lit_ids,
+ lit_edge_map, false);
+ frag.delay_program_offset
+ = writeDelayRebuildProgram(build, bc, prog_build, frag.lit_ids);
}
}
* programs.
*/
static
-pair<u32, u32> writeDelayPrograms(const RoseBuildImpl &build, build_context &bc,
+pair<u32, u32> writeDelayPrograms(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments,
+ build_context &bc,
ProgramBuild &prog_build) {
auto lit_edge_map = findEdgesByLiteral(build);
vector<u32> programs; // program offsets indexed by (delayed) lit id
unordered_map<u32, u32> cache; // program offsets we have already seen
- for (const auto &lit_id : build.literals.right | map_keys) {
- const auto &info = build.literal_info.at(lit_id);
-
- if (info.fragment_id == MO_INVALID_IDX) {
- continue; // Unused literal.
- }
-
- for (const auto &delayed_lit_id : info.delayed_ids) {
- DEBUG_PRINTF("lit id %u delay id %u\n", lit_id, delayed_lit_id);
- u32 offset = writeLiteralProgram(
- build, bc, prog_build, {delayed_lit_id}, lit_edge_map, false);
-
- u32 delay_id;
- auto it = cache.find(offset);
- if (it != end(cache)) {
- delay_id = it->second;
- DEBUG_PRINTF("reusing delay_id %u for offset %u\n", delay_id,
- offset);
- } else {
- delay_id = verify_u32(programs.size());
- programs.push_back(offset);
- cache.emplace(offset, delay_id);
- DEBUG_PRINTF("assigned new delay_id %u for offset %u\n",
- delay_id, offset);
+ for (const auto &frag : fragments) {
+ for (const u32 lit_id : frag.lit_ids) {
+ const auto &info = build.literal_info.at(lit_id);
+
+ for (const auto &delayed_lit_id : info.delayed_ids) {
+ DEBUG_PRINTF("lit id %u delay id %u\n", lit_id, delayed_lit_id);
+ u32 offset = writeLiteralProgram(build, bc, prog_build,
+ {delayed_lit_id}, lit_edge_map,
+ false);
+
+ u32 delay_id;
+ auto it = cache.find(offset);
+ if (it != end(cache)) {
+ delay_id = it->second;
+ DEBUG_PRINTF("reusing delay_id %u for offset %u\n",
+ delay_id, offset);
+ } else {
+ delay_id = verify_u32(programs.size());
+ programs.push_back(offset);
+ cache.emplace(offset, delay_id);
+ DEBUG_PRINTF("assigned new delay_id %u for offset %u\n",
+ delay_id, offset);
+ }
+ prog_build.delay_programs.emplace(delayed_lit_id, delay_id);
}
- prog_build.delay_programs.emplace(delayed_lit_id, delay_id);
}
}
*/
static
pair<u32, u32> writeAnchoredPrograms(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments,
build_context &bc,
ProgramBuild &prog_build) {
auto lit_edge_map = findEdgesByLiteral(build);
vector<u32> programs; // program offsets indexed by anchored id
unordered_map<u32, u32> cache; // program offsets we have already seen
- for (const auto &m : build.literals.right) {
- u32 lit_id = m.first;
- const auto &lit = m.second;
+ for (const auto &frag : fragments) {
+ for (const u32 lit_id : frag.lit_ids) {
+ const auto &lit = build.literals.right.at(lit_id);
- if (lit.table != ROSE_ANCHORED) {
- continue;
- }
-
- if (build.literal_info.at(lit_id).fragment_id == MO_INVALID_IDX) {
- continue; // Unused literal.
- }
+ if (lit.table != ROSE_ANCHORED) {
+ continue;
+ }
- // If this anchored literal can never match past
- // floatingMinLiteralMatchOffset, we will never have to record it.
- if (findMaxOffset(build, lit_id) <= bc.floatingMinLiteralMatchOffset) {
- DEBUG_PRINTF("can never match after "
- "floatingMinLiteralMatchOffset=%u\n",
- bc.floatingMinLiteralMatchOffset);
- continue;
- }
+ // If this anchored literal can never match past
+ // floatingMinLiteralMatchOffset, we will never have to record it.
+ if (findMaxOffset(build, lit_id)
+ <= prog_build.floatingMinLiteralMatchOffset) {
+ DEBUG_PRINTF("can never match after "
+ "floatingMinLiteralMatchOffset=%u\n",
+ prog_build.floatingMinLiteralMatchOffset);
+ continue;
+ }
- u32 offset = writeLiteralProgram(build, bc, prog_build, {lit_id},
- lit_edge_map, true);
- DEBUG_PRINTF("lit_id=%u -> anch prog at %u\n", lit_id, offset);
+ u32 offset = writeLiteralProgram(build, bc, prog_build, {lit_id},
+ lit_edge_map, true);
+ DEBUG_PRINTF("lit_id=%u -> anch prog at %u\n", lit_id, offset);
- u32 anch_id;
- auto it = cache.find(offset);
- if (it != end(cache)) {
- anch_id = it->second;
- DEBUG_PRINTF("reusing anch_id %u for offset %u\n", anch_id, offset);
- } else {
- anch_id = verify_u32(programs.size());
- programs.push_back(offset);
- cache.emplace(offset, anch_id);
- DEBUG_PRINTF("assigned new anch_id %u for offset %u\n", anch_id,
- offset);
+ u32 anch_id;
+ auto it = cache.find(offset);
+ if (it != end(cache)) {
+ anch_id = it->second;
+ DEBUG_PRINTF("reusing anch_id %u for offset %u\n", anch_id, offset);
+ } else {
+ anch_id = verify_u32(programs.size());
+ programs.push_back(offset);
+ cache.emplace(offset, anch_id);
+ DEBUG_PRINTF("assigned new anch_id %u for offset %u\n", anch_id,
+ offset);
+ }
+ prog_build.anchored_programs.emplace(lit_id, anch_id);
}
- prog_build.anchored_programs.emplace(lit_id, anch_id);
}
DEBUG_PRINTF("%zu anchored programs\n", programs.size());
for (ReportID id : reports) {
RoseProgram program;
const bool has_som = false;
- makeCatchupMpv(build, bc, id, program);
+ makeCatchupMpv(build, bc.needs_mpv_catchup, id, program);
makeReport(build, id, has_som, program);
applyFinalSpecialisation(program);
u32 offset = writeProgram(bc, move(program));
static
RoseProgram makeEodAnchorProgram(const RoseBuildImpl &build,
- const build_context &bc,
+ bool needs_catchup,
ProgramBuild &prog_build, const RoseEdge &e,
const bool multiple_preds) {
const RoseGraph &g = build.g;
}
const auto &reports = g[v].reports;
- makeCatchup(build, bc, reports, program);
+ makeCatchup(build, needs_catchup, reports, program);
const bool has_som = false;
RoseProgram report_block;
assert(contains(bc.roleStateIndices, u));
u32 pred_state = bc.roleStateIndices.at(u);
pred_blocks[pred_state].add_block(
- makeEodAnchorProgram(build, bc, prog_build, e, multiple_preds));
+ makeEodAnchorProgram(build, bc.needs_catchup, prog_build, e,
+ multiple_preds));
}
}
- addPredBlocks(bc, pred_blocks, program);
+ addPredBlocks(pred_blocks, bc.roleStateIndices.size(), program);
}
static
static
u32 writeEagerQueueIter(const set<u32> &eager, u32 leftfixBeginQueue,
- u32 queue_count, build_context &bc) {
+ u32 queue_count, RoseEngineBlob &engine_blob) {
if (eager.empty()) {
return 0;
}
vec.push_back(q - leftfixBeginQueue);
}
- vector<mmbit_sparse_iter> iter;
- mmbBuildSparseIterator(iter, vec, queue_count - leftfixBeginQueue);
- return bc.engine_blob.add_iterator(iter);
+ auto iter = mmbBuildSparseIterator(vec, queue_count - leftfixBeginQueue);
+ return engine_blob.add_iterator(iter);
}
static
return longLitLengthThreshold;
}
+static
+map<left_id, u32> makeLeftQueueMap(const RoseGraph &g,
+ const map<RoseVertex, left_build_info> &leftfix_info) {
+ map<left_id, u32> lqm;
+ for (const auto &e : leftfix_info) {
+ left_id left(g[e.first].left);
+ assert(!contains(lqm, left) || lqm[left] == e.second.queue);
+ lqm[left] = e.second.queue;
+ }
+
+ return lqm;
+}
+
aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
// We keep all our offsets, counts etc. in a prototype RoseEngine which we
// will copy into the real one once it is allocated: we can't do this
historyRequired);
DEBUG_PRINTF("longLitLengthThreshold=%zu\n", longLitLengthThreshold);
- groupByFragment(*this);
+ vector<LitFragment> fragments = groupByFragment(*this);
- auto anchored_dfas = buildAnchoredDfas(*this);
+ auto anchored_dfas = buildAnchoredDfas(*this, fragments);
build_context bc;
- bc.floatingMinLiteralMatchOffset =
- findMinFloatingLiteralMatch(*this, anchored_dfas);
+ u32 floatingMinLiteralMatchOffset
+ = findMinFloatingLiteralMatch(*this, anchored_dfas);
bc.longLitLengthThreshold = longLitLengthThreshold;
bc.needs_catchup = needsCatchup(*this, anchored_dfas);
- recordResources(bc.resources, *this);
+ recordResources(bc.resources, *this, fragments);
if (!anchored_dfas.empty()) {
bc.resources.has_anchored = true;
}
throw ResourceLimitError();
}
- assignStateIndices(*this, bc);
+ // Enforce role table resource limit.
+ if (num_vertices(g) > cc.grey.limitRoseRoleCount) {
+ throw ResourceLimitError();
+ }
+
+ bc.roleStateIndices = assignStateIndices(*this);
u32 laggedRoseCount = 0;
vector<LeftNfaInfo> leftInfoTable;
&laggedRoseCount, &historyRequired);
// Information only needed for program construction.
- ProgramBuild prog_build;
+ ProgramBuild prog_build(floatingMinLiteralMatchOffset);
prog_build.vertex_group_map = getVertexGroupMap(*this);
prog_build.squashable_groups = getSquashableGroups(*this);
tie(proto.anchoredProgramOffset, proto.anchored_count) =
- writeAnchoredPrograms(*this, bc, prog_build);
+ writeAnchoredPrograms(*this, fragments, bc, prog_build);
tie(proto.delayProgramOffset, proto.delay_count) =
- writeDelayPrograms(*this, bc, prog_build);
+ writeDelayPrograms(*this, fragments, bc, prog_build);
- buildLiteralPrograms(*this, bc, prog_build);
+ buildLiteralPrograms(*this, fragments, bc, prog_build);
proto.eodProgramOffset =
writeEodProgram(*this, bc, prog_build, eodNfaIterOffset);
proto.lastByteHistoryIterOffset = buildLastByteIter(g, bc);
proto.eagerIterOffset = writeEagerQueueIter(
- eager_queues, proto.leftfixBeginQueue, queue_count, bc);
+ eager_queues, proto.leftfixBeginQueue, queue_count, bc.engine_blob);
addSomRevNfas(bc, proto, ssm);
writeLookaroundTables(bc, proto);
- writeDkeyInfo(rm, bc, proto);
- writeLeftInfo(bc, proto, leftInfoTable);
-
- // Enforce role table resource limit.
- if (num_vertices(g) > cc.grey.limitRoseRoleCount) {
- throw ResourceLimitError();
- }
+ writeDkeyInfo(rm, bc.engine_blob, proto);
+ writeLeftInfo(bc.engine_blob, proto, leftInfoTable);
// Build anchored matcher.
size_t asize = 0;
- auto atable = buildAnchoredMatcher(*this, anchored_dfas, &asize);
+ auto atable = buildAnchoredMatcher(*this, fragments, anchored_dfas, &asize);
if (atable) {
proto.amatcherOffset = bc.engine_blob.add(atable.get(), asize, 64);
}
// Build floating HWLM matcher.
rose_group fgroups = 0;
size_t fsize = 0;
- auto ftable = buildFloatingMatcher(*this, bc.longLitLengthThreshold,
+ auto ftable = buildFloatingMatcher(*this, fragments,
+ bc.longLitLengthThreshold,
&fgroups, &fsize, &historyRequired);
if (ftable) {
proto.fmatcherOffset = bc.engine_blob.add(ftable.get(), fsize, 64);
// Build delay rebuild HWLM matcher.
size_t drsize = 0;
- auto drtable =
- buildDelayRebuildMatcher(*this, bc.longLitLengthThreshold, &drsize);
+ auto drtable = buildDelayRebuildMatcher(*this, fragments,
+ bc.longLitLengthThreshold, &drsize);
if (drtable) {
proto.drmatcherOffset = bc.engine_blob.add(drtable.get(), drsize, 64);
}
// Build EOD-anchored HWLM matcher.
size_t esize = 0;
- auto etable = buildEodAnchoredMatcher(*this, &esize);
+ auto etable = buildEodAnchoredMatcher(*this, fragments, &esize);
if (etable) {
proto.ematcherOffset = bc.engine_blob.add(etable.get(), esize, 64);
}
// Build small-block HWLM matcher.
size_t sbsize = 0;
- auto sbtable = buildSmallBlockMatcher(*this, &sbsize);
+ auto sbtable = buildSmallBlockMatcher(*this, fragments, &sbsize);
if (sbtable) {
proto.sbmatcherOffset = bc.engine_blob.add(sbtable.get(), sbsize, 64);
}
assert(!cc.streaming || historyRequired <=
max(cc.grey.maxHistoryAvailable, cc.grey.somMaxRevNfaLength));
- fillStateOffsets(*this, bc.numStates, proto.anchorStateSize,
+ fillStateOffsets(*this, bc.roleStateIndices.size(), proto.anchorStateSize,
proto.activeArrayCount, proto.activeLeftCount,
laggedRoseCount, longLitStreamStateRequired,
historyRequired, &proto.stateOffsets);
writeNfaInfo(*this, bc, proto, no_retrigger_queues);
scatter_plan_raw state_scatter = buildStateScatterPlan(
- sizeof(u8), bc.numStates, proto.activeLeftCount, proto.rosePrefixCount,
- proto.stateOffsets, cc.streaming, proto.activeArrayCount,
- proto.outfixBeginQueue, proto.outfixEndQueue);
+ sizeof(u8), bc.roleStateIndices.size(), proto.activeLeftCount,
+ proto.rosePrefixCount, proto.stateOffsets, cc.streaming,
+ proto.activeArrayCount, proto.outfixBeginQueue, proto.outfixEndQueue);
u32 currOffset; /* relative to base of RoseEngine */
if (!bc.engine_blob.empty()) {
proto.needsCatchup = bc.needs_catchup ? 1 : 0;
- proto.runtimeImpl = pickRuntimeImpl(*this, bc, proto.outfixEndQueue);
+ proto.runtimeImpl = pickRuntimeImpl(*this, bc.resources,
+ proto.outfixEndQueue);
proto.mpvTriggeredByLeaf = anyEndfixMpvTriggers(*this);
proto.queueCount = queue_count;
proto.handledKeyCount = prog_build.handledKeys.size();
proto.handledKeyFatbitSize = fatbit_size(proto.handledKeyCount);
- proto.rolesWithStateCount = bc.numStates;
+ proto.rolesWithStateCount = bc.roleStateIndices.size();
proto.initMpvNfa = mpv_as_outfix ? 0 : MO_INVALID_IDX;
- proto.stateSize = mmbit_size(bc.numStates);
+ proto.stateSize = mmbit_size(bc.roleStateIndices.size());
proto.delay_fatbit_size = fatbit_size(proto.delay_count);
proto.anchored_fatbit_size = fatbit_size(proto.anchored_count);
proto.fmatcherMaxBiAnchoredWidth = findMaxBAWidth(*this, ROSE_FLOATING);
proto.minWidth = hasBoundaryReports(boundary) ? 0 : minWidth;
proto.minWidthExcludingBoundaries = minWidth;
- proto.floatingMinLiteralMatchOffset = bc.floatingMinLiteralMatchOffset;
+ proto.floatingMinLiteralMatchOffset = floatingMinLiteralMatchOffset;
proto.maxBiAnchoredWidth = findMaxBAWidth(*this);
proto.noFloatingRoots = hasNoFloatingRoots();
DEBUG_PRINTF("rose done %p\n", engine.get());
- dumpRose(*this, engine.get());
+ dumpRose(*this, fragments, makeLeftQueueMap(g, bc.leftfix_info),
+ bc.suffixes, engine.get());
return engine;
}
const u32 id = e.first;
const auto &lit = e.second;
- // This pass takes place before fragment IDs are assigned to literals.
- assert(build.literal_info.at(id).fragment_id == MO_INVALID_IDX);
-
if (lit.delay || build.isDelayed(id)) {
continue;
}
*/
static
MatcherProto makeMatcherProto(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments,
rose_literal_table table, bool delay_rebuild,
size_t max_len, u32 max_offset = ROSE_BOUND_INF) {
MatcherProto mp;
assert(build.cc.streaming);
}
- for (const auto &e : build.literals.right) {
- const u32 id = e.first;
- if (build.literal_info.at(id).fragment_id == MO_INVALID_IDX) {
- continue;
- }
+ for (const auto &f : fragments) {
+ for (u32 id : f.lit_ids) {
+ const rose_literal_id &lit = build.literals.right.at(id);
- if (e.second.delay) {
- continue; /* delay id's are virtual-ish */
- }
+ if (lit.table != table) {
+ continue; /* wrong table */
+ }
- if (e.second.table != table) {
- continue; /* wrong table */
- }
+ if (lit.delay) {
+ continue; /* delay id's are virtual-ish */
+ }
- assert(id < build.literal_info.size());
- const rose_literal_info &info = build.literal_info[id];
- /* Note: requires_benefits are handled in the literal entries */
- const ue2_literal &lit = e.second.s;
+ assert(id < build.literal_info.size());
+ const auto &info = build.literal_info.at(id);
- DEBUG_PRINTF("lit='%s' (len %zu)\n", escapeString(lit).c_str(),
- lit.length());
+ /* Note: requires_benefits are handled in the literal entries */
+ const ue2_literal &s = lit.s;
- // When building the delay rebuild table, we only want to include
- // literals that have delayed variants.
- if (delay_rebuild && info.delayed_ids.empty()) {
- DEBUG_PRINTF("not needed for delay rebuild\n");
- continue;
- }
+ DEBUG_PRINTF("lit='%s' (len %zu)\n", escapeString(s).c_str(),
+ s.length());
- if (max_offset != ROSE_BOUND_INF) {
- u64a min_report = literalMinReportOffset(build, e.second, info);
- if (min_report > max_offset) {
- DEBUG_PRINTF("min report offset=%llu exceeds max_offset=%u\n",
- min_report, max_offset);
+ // When building the delay rebuild table, we only want to include
+ // literals that have delayed variants.
+ if (delay_rebuild && info.delayed_ids.empty()) {
+ DEBUG_PRINTF("not needed for delay rebuild\n");
continue;
}
- }
- const vector<u8> &msk = e.second.msk;
- const vector<u8> &cmp = e.second.cmp;
- bool noruns = isNoRunsLiteral(build, id, info, max_len);
+ if (max_offset != ROSE_BOUND_INF) {
+ u64a min_report = literalMinReportOffset(build, lit, info);
+ if (min_report > max_offset) {
+ DEBUG_PRINTF("min report offset=%llu exceeds "
+ "max_offset=%u\n", min_report, max_offset);
+ continue;
+ }
+ }
- size_t lit_hist_len = 0;
- if (build.cc.streaming) {
- lit_hist_len = max(msk.size(), min(lit.length(), max_len));
- lit_hist_len = lit_hist_len ? lit_hist_len - 1 : 0;
- }
- DEBUG_PRINTF("lit requires %zu bytes of history\n", lit_hist_len);
- assert(lit_hist_len <= build.cc.grey.maxHistoryAvailable);
-
- auto lit_final = lit; // copy
-
- if (lit_final.length() > ROSE_SHORT_LITERAL_LEN_MAX) {
- DEBUG_PRINTF("truncating to tail of length %zu\n",
- size_t{ROSE_SHORT_LITERAL_LEN_MAX});
- lit_final.erase(0, lit_final.length() - ROSE_SHORT_LITERAL_LEN_MAX);
- // We shouldn't have set a threshold below 8 chars.
- assert(msk.size() <= ROSE_SHORT_LITERAL_LEN_MAX);
- assert(!noruns);
- }
+ const vector<u8> &msk = lit.msk;
+ const vector<u8> &cmp = lit.cmp;
+ bool noruns = isNoRunsLiteral(build, id, info, max_len);
- const auto &s = lit_final.get_string();
- bool nocase = lit_final.any_nocase();
+ size_t lit_hist_len = 0;
+ if (build.cc.streaming) {
+ lit_hist_len = max(msk.size(), min(s.length(), max_len));
+ lit_hist_len = lit_hist_len ? lit_hist_len - 1 : 0;
+ }
+ DEBUG_PRINTF("lit requires %zu bytes of history\n", lit_hist_len);
+ assert(lit_hist_len <= build.cc.grey.maxHistoryAvailable);
+
+ auto lit_final = s; // copy
+
+ if (lit_final.length() > ROSE_SHORT_LITERAL_LEN_MAX) {
+ DEBUG_PRINTF("truncating to tail of length %zu\n",
+ size_t{ROSE_SHORT_LITERAL_LEN_MAX});
+ lit_final.erase(0, lit_final.length()
+ - ROSE_SHORT_LITERAL_LEN_MAX);
+ // We shouldn't have set a threshold below 8 chars.
+ assert(msk.size() <= ROSE_SHORT_LITERAL_LEN_MAX);
+ assert(!noruns);
+ }
- DEBUG_PRINTF("id=%u, s='%s', nocase=%d, noruns=%d, msk=%s, "
- "cmp=%s\n",
- info.fragment_id, escapeString(s).c_str(), (int)nocase,
- noruns, dumpMask(msk).c_str(), dumpMask(cmp).c_str());
+ const auto &s_final = lit_final.get_string();
+ bool nocase = lit_final.any_nocase();
- if (!maskIsConsistent(s, nocase, msk, cmp)) {
- DEBUG_PRINTF("msk/cmp for literal can't match, skipping\n");
- continue;
- }
+ DEBUG_PRINTF("id=%u, s='%s', nocase=%d, noruns=%d, msk=%s, "
+ "cmp=%s\n", f.fragment_id,
+ escapeString(s_final).c_str(), (int)nocase, noruns,
+ dumpMask(msk).c_str(), dumpMask(cmp).c_str());
- mp.accel_lits.emplace_back(lit.get_string(), lit.any_nocase(), msk, cmp,
- info.group_mask);
- mp.history_required = max(mp.history_required, lit_hist_len);
+ if (!maskIsConsistent(s_final, nocase, msk, cmp)) {
+ DEBUG_PRINTF("msk/cmp for literal can't match, skipping\n");
+ continue;
+ }
+
+ mp.accel_lits.emplace_back(s.get_string(), s.any_nocase(), msk, cmp,
+ info.group_mask);
+ mp.history_required = max(mp.history_required, lit_hist_len);
- assert(info.fragment_id < build.fragments.size());
- const auto &frag = build.fragments.at(info.fragment_id);
- u32 prog_offset =
- delay_rebuild ? frag.delay_program_offset : frag.lit_program_offset;
- const auto &groups = frag.groups;
+ u32 prog_offset = delay_rebuild ? f.delay_program_offset
+ : f.lit_program_offset;
+ const auto &groups = f.groups;
- mp.lits.emplace_back(move(s), nocase, noruns, prog_offset, groups, msk,
- cmp);
+ mp.lits.emplace_back(move(s_final), nocase, noruns, prog_offset,
+ groups, msk, cmp);
+ }
}
sort_and_unique(mp.lits);
}
aligned_unique_ptr<HWLM>
-buildFloatingMatcher(const RoseBuildImpl &build, size_t longLitLengthThreshold,
- rose_group *fgroups, size_t *fsize,
- size_t *historyRequired) {
+buildFloatingMatcher(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments,
+ size_t longLitLengthThreshold, rose_group *fgroups,
+ size_t *fsize, size_t *historyRequired) {
*fsize = 0;
*fgroups = 0;
- auto mp =
- makeMatcherProto(build, ROSE_FLOATING, false, longLitLengthThreshold);
+ auto mp = makeMatcherProto(build, fragments, ROSE_FLOATING, false,
+ longLitLengthThreshold);
if (mp.lits.empty()) {
DEBUG_PRINTF("empty floating matcher\n");
return nullptr;
}
aligned_unique_ptr<HWLM> buildDelayRebuildMatcher(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments,
size_t longLitLengthThreshold,
size_t *drsize) {
*drsize = 0;
return nullptr;
}
- auto mp =
- makeMatcherProto(build, ROSE_FLOATING, true, longLitLengthThreshold);
+ auto mp = makeMatcherProto(build, fragments, ROSE_FLOATING, true,
+ longLitLengthThreshold);
if (mp.lits.empty()) {
DEBUG_PRINTF("empty delay rebuild matcher\n");
return nullptr;
return hwlm;
}
-aligned_unique_ptr<HWLM> buildSmallBlockMatcher(const RoseBuildImpl &build,
- size_t *sbsize) {
+aligned_unique_ptr<HWLM>
+buildSmallBlockMatcher(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments, size_t *sbsize) {
*sbsize = 0;
if (build.cc.streaming) {
return nullptr;
}
- auto mp = makeMatcherProto(build, ROSE_FLOATING, false,
+ auto mp = makeMatcherProto(build, fragments, ROSE_FLOATING, false,
ROSE_SMALL_BLOCK_LEN, ROSE_SMALL_BLOCK_LEN);
if (mp.lits.empty()) {
DEBUG_PRINTF("no floating table\n");
return nullptr;
}
- auto mp_anchored =
- makeMatcherProto(build, ROSE_ANCHORED_SMALL_BLOCK, false,
- ROSE_SMALL_BLOCK_LEN, ROSE_SMALL_BLOCK_LEN);
+ auto mp_anchored = makeMatcherProto(build, fragments,
+ ROSE_ANCHORED_SMALL_BLOCK, false,
+ ROSE_SMALL_BLOCK_LEN,
+ ROSE_SMALL_BLOCK_LEN);
if (mp_anchored.lits.empty()) {
DEBUG_PRINTF("no small-block anchored literals\n");
return nullptr;
return hwlm;
}
-aligned_unique_ptr<HWLM> buildEodAnchoredMatcher(const RoseBuildImpl &build,
- size_t *esize) {
+aligned_unique_ptr<HWLM>
+buildEodAnchoredMatcher(const RoseBuildImpl &build,
+ const vector<LitFragment> &fragments, size_t *esize) {
*esize = 0;
- auto mp = makeMatcherProto(build, ROSE_EOD_ANCHORED, false,
+ auto mp = makeMatcherProto(build, fragments, ROSE_EOD_ANCHORED, false,
build.ematcher_region_size);
if (mp.lits.empty()) {