]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
Rose: be more precise with CATCHUP instruction
authorJustin Viiret <justin.viiret@intel.com>
Fri, 4 Mar 2016 02:54:30 +0000 (13:54 +1100)
committerMatthew Barr <matthew.barr@intel.com>
Wed, 20 Apr 2016 03:34:54 +0000 (13:34 +1000)
- Fix bugs introduced by recent addition of the boundary program. It's
  not safe to do catchup there.
- Only do catchup once per report set, when necessary.

src/rose/match.c
src/rose/rose_build_bytecode.cpp

index 9163cba3a66c52e8c6ba60e387d1f6895aaf6843..9ff7db06d5bf4f0e60270c04cbafa8eb7880dd9b 100644 (file)
@@ -599,6 +599,12 @@ int roseRunBoundaryProgram(const struct RoseEngine *rose, u32 program,
         scratch->deduper.som_log_dirty = 0;
     }
 
+    // Keep assertions in program report path happy. At offset zero, there can
+    // have been no earlier reports. At EOD, all earlier reports should have
+    // been handled and we will have been caught up to the stream offset by the
+    // time we are running boundary report programs.
+    scratch->tctxt.minMatchOffset = stream_offset;
+
     const size_t match_len = 0;
     const char in_anchored = 0;
     hwlmcb_rv_t rv = roseRunProgram(rose, scratch, program, stream_offset,
index bb11b1a74f261ad9f912a34626ca870a296add47..51a0eeef1b8ef21de15c514fec3fc926a3890146 100644 (file)
@@ -2486,6 +2486,30 @@ void makeDedupeSom(const ReportID id, vector<RoseInstruction> &report_block) {
     report_block.push_back(move(ri));
 }
 
+static
+void makeCatchup(RoseBuildImpl &build, build_context &bc,
+                 const flat_set<ReportID> &reports,
+                 vector<RoseInstruction> &program) {
+    if (!bc.needs_catchup) {
+        return;
+    }
+
+    // Everything except the INTERNAL_ROSE_CHAIN report needs catchup to run
+    // before reports are triggered.
+
+    auto report_needs_catchup = [&](const ReportID &id) {
+        const Report &report = build.rm.getReport(id);
+        return report.type != INTERNAL_ROSE_CHAIN;
+    };
+
+    if (!any_of(begin(reports), end(reports), report_needs_catchup)) {
+        DEBUG_PRINTF("none of the given reports needs catchup\n");
+        return;
+    }
+
+    program.emplace_back(ROSE_INSTR_CATCH_UP);
+}
+
 static
 void makeReport(RoseBuildImpl &build, build_context &bc, const ReportID id,
                 const bool has_som, vector<RoseInstruction> &program) {
@@ -2503,13 +2527,6 @@ void makeReport(RoseBuildImpl &build, build_context &bc, const ReportID id,
         report_block.push_back(move(ri));
     }
 
-    // Catch up -- everything except the INTERNAL_ROSE_CHAIN report needs this.
-    // TODO: this could be floated in front of all the reports and only done
-    // once.
-    if (bc.needs_catchup && report.type != INTERNAL_ROSE_CHAIN) {
-        report_block.emplace_back(ROSE_INSTR_CATCH_UP);
-    }
-
     // If this report has an exhaustion key, we can check it in the program
     // rather than waiting until we're in the callback adaptor.
     if (report.ekey != INVALID_EKEY) {
@@ -2651,7 +2668,10 @@ void makeRoleReports(RoseBuildImpl &build, build_context &bc, RoseVertex v,
         has_som = true;
     }
 
-    for (ReportID id : g[v].reports) {
+    const auto &reports = g[v].reports;
+    makeCatchup(build, bc, reports, program);
+
+    for (ReportID id : reports) {
         makeReport(build, bc, id, has_som, program);
     }
 }
@@ -2860,6 +2880,10 @@ u32 writeBoundaryProgram(RoseBuildImpl &build, build_context &bc,
         return 0;
     }
 
+    // Note: no CATCHUP instruction is necessary in the boundary case, as we
+    // should always be caught up (and may not even have the resources in
+    // scratch to support it).
+
     const bool has_som = false;
     vector<RoseInstruction> program;
     for (const auto &id : reports) {
@@ -3565,8 +3589,11 @@ vector<RoseInstruction> makeEodAnchorProgram(RoseBuildImpl &build,
         makeRoleCheckNotHandled(bc, v, program);
     }
 
+    const auto &reports = g[v].reports;
+    makeCatchup(build, bc, reports, program);
+
     const bool has_som = false;
-    for (const auto &id : g[v].reports) {
+    for (const auto &id : reports) {
         makeReport(build, bc, id, has_som, program);
     }