Rose: be more precise with CATCHUP instruction

- 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.
This commit is contained in:
Justin Viiret 2016-03-04 13:54:30 +11:00 committed by Matthew Barr
parent e466e67b79
commit ff7e101757
2 changed files with 42 additions and 9 deletions

View 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,

View 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);
}