mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
FINAL_REPORT: Add specialised instruction
Specialisation of the REPORT instruction that also terminates execution of the program. Improves performance on programs that generate many reports.
This commit is contained in:
parent
36150bbc19
commit
1d85987d96
@ -1165,6 +1165,18 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(FINAL_REPORT) {
|
||||
updateSeqPoint(tctxt, end, from_mpv);
|
||||
if (roseReport(t, scratch, end, ri->onmatch, ri->offset_adjust,
|
||||
INVALID_EKEY) == HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
/* One-shot specialisation: this instruction always terminates
|
||||
* execution of the program. */
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(CHECK_EXHAUSTED) {
|
||||
DEBUG_PRINTF("check ekey %u\n", ri->ekey);
|
||||
assert(ri->ekey != INVALID_EKEY);
|
||||
|
@ -212,6 +212,7 @@ public:
|
||||
case ROSE_INSTR_REPORT_SOM: return &u.reportSom;
|
||||
case ROSE_INSTR_REPORT_SOM_EXHAUST: return &u.reportSomExhaust;
|
||||
case ROSE_INSTR_DEDUPE_AND_REPORT: return &u.dedupeAndReport;
|
||||
case ROSE_INSTR_FINAL_REPORT: return &u.finalReport;
|
||||
case ROSE_INSTR_CHECK_EXHAUSTED: return &u.checkExhausted;
|
||||
case ROSE_INSTR_CHECK_MIN_LENGTH: return &u.checkMinLength;
|
||||
case ROSE_INSTR_SET_STATE: return &u.setState;
|
||||
@ -257,6 +258,7 @@ public:
|
||||
case ROSE_INSTR_REPORT_SOM: return sizeof(u.reportSom);
|
||||
case ROSE_INSTR_REPORT_SOM_EXHAUST: return sizeof(u.reportSomExhaust);
|
||||
case ROSE_INSTR_DEDUPE_AND_REPORT: return sizeof(u.dedupeAndReport);
|
||||
case ROSE_INSTR_FINAL_REPORT: return sizeof(u.finalReport);
|
||||
case ROSE_INSTR_CHECK_EXHAUSTED: return sizeof(u.checkExhausted);
|
||||
case ROSE_INSTR_CHECK_MIN_LENGTH: return sizeof(u.checkMinLength);
|
||||
case ROSE_INSTR_SET_STATE: return sizeof(u.setState);
|
||||
@ -301,6 +303,7 @@ public:
|
||||
ROSE_STRUCT_REPORT_SOM reportSom;
|
||||
ROSE_STRUCT_REPORT_SOM_EXHAUST reportSomExhaust;
|
||||
ROSE_STRUCT_DEDUPE_AND_REPORT dedupeAndReport;
|
||||
ROSE_STRUCT_FINAL_REPORT finalReport;
|
||||
ROSE_STRUCT_CHECK_EXHAUSTED checkExhausted;
|
||||
ROSE_STRUCT_CHECK_MIN_LENGTH checkMinLength;
|
||||
ROSE_STRUCT_SET_STATE setState;
|
||||
@ -2160,6 +2163,31 @@ flattenProgram(const vector<vector<RoseInstruction>> &programs) {
|
||||
return out;
|
||||
}
|
||||
|
||||
static
|
||||
void applyFinalSpecialisation(vector<RoseInstruction> &program) {
|
||||
assert(!program.empty());
|
||||
assert(program.back().code() == ROSE_INSTR_END);
|
||||
if (program.size() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Replace the second-to-last instruction (before END) with a one-shot
|
||||
* specialisation if available. */
|
||||
auto &ri = *(next(program.rbegin()));
|
||||
switch (ri.code()) {
|
||||
case ROSE_INSTR_REPORT: {
|
||||
DEBUG_PRINTF("replacing REPORT with FINAL_REPORT\n");
|
||||
auto ri2 = RoseInstruction(ROSE_INSTR_FINAL_REPORT);
|
||||
ri2.u.finalReport.onmatch = ri.u.report.onmatch;
|
||||
ri2.u.finalReport.offset_adjust = ri.u.report.offset_adjust;
|
||||
ri = ri2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void recordResources(RoseResources &resources,
|
||||
const vector<RoseInstruction> &program) {
|
||||
@ -3020,7 +3048,9 @@ u32 writeBoundaryProgram(RoseBuildImpl &build, build_context &bc,
|
||||
for (const auto &id : reports) {
|
||||
makeReport(build, id, has_som, program);
|
||||
}
|
||||
return writeProgram(bc, flattenProgram({program}));
|
||||
program = flattenProgram({program});
|
||||
applyFinalSpecialisation(program);
|
||||
return writeProgram(bc, program);
|
||||
}
|
||||
|
||||
static
|
||||
@ -3374,6 +3404,7 @@ pair<u32, u32> makeSparseIterProgram(build_context &bc,
|
||||
program.insert(end(program), begin(root_program), end(root_program));
|
||||
}
|
||||
|
||||
applyFinalSpecialisation(program);
|
||||
return {writeProgram(bc, program), iter_offset};
|
||||
}
|
||||
|
||||
@ -3634,6 +3665,7 @@ u32 buildDelayRebuildProgram(RoseBuildImpl &build, build_context &bc,
|
||||
makePushDelayedInstructions(build, final_id, program);
|
||||
assert(!program.empty());
|
||||
program = flattenProgram({program});
|
||||
applyFinalSpecialisation(program);
|
||||
return writeProgram(bc, program);
|
||||
}
|
||||
|
||||
@ -3714,7 +3746,9 @@ u32 buildReportPrograms(RoseBuildImpl &build, build_context &bc) {
|
||||
const bool has_som = false;
|
||||
makeCatchupMpv(build, bc, id, program);
|
||||
makeReport(build, id, has_som, program);
|
||||
programs[id] = writeProgram(bc, flattenProgram({program}));
|
||||
program = flattenProgram({program});
|
||||
applyFinalSpecialisation(program);
|
||||
programs[id] = writeProgram(bc, program);
|
||||
DEBUG_PRINTF("program for report %u @ %u (%zu instructions)\n", id,
|
||||
programs.back(), program.size());
|
||||
}
|
||||
@ -3792,6 +3826,7 @@ pair<u32, u32> buildEodAnchorProgram(RoseBuildImpl &build, build_context &bc) {
|
||||
u32 iter_offset = addPredBlocks(bc, predProgramLists, program, true);
|
||||
|
||||
assert(program.size() > 1);
|
||||
applyFinalSpecialisation(program);
|
||||
return {writeProgram(bc, program), iter_offset};
|
||||
}
|
||||
|
||||
|
@ -416,6 +416,12 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(FINAL_REPORT) {
|
||||
os << " onmatch " << ri->onmatch << endl;
|
||||
os << " offset_adjust " << ri->offset_adjust << endl;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(CHECK_EXHAUSTED) {
|
||||
os << " ekey " << ri->ekey << endl;
|
||||
os << " fail_jump " << offset + ri->fail_jump << endl;
|
||||
|
@ -82,6 +82,12 @@ enum RoseInstructionCode {
|
||||
/** \brief Super-instruction combining DEDUPE and REPORT. */
|
||||
ROSE_INSTR_DEDUPE_AND_REPORT,
|
||||
|
||||
/**
|
||||
* \brief Fire a report and stop program execution. This is a
|
||||
* specialisation intended for short, frequently-executed programs.
|
||||
*/
|
||||
ROSE_INSTR_FINAL_REPORT,
|
||||
|
||||
ROSE_INSTR_CHECK_EXHAUSTED, //!< Check if an ekey has already been set.
|
||||
ROSE_INSTR_CHECK_MIN_LENGTH, //!< Check (EOM - SOM) against min length.
|
||||
ROSE_INSTR_SET_STATE, //!< Switch a state index on.
|
||||
@ -282,6 +288,12 @@ struct ROSE_STRUCT_DEDUPE_AND_REPORT {
|
||||
u32 fail_jump; //!< Jump forward this many bytes on failure.
|
||||
};
|
||||
|
||||
struct ROSE_STRUCT_FINAL_REPORT {
|
||||
u8 code; //!< From enum RoseInstructionCode.
|
||||
ReportID onmatch; //!< Report ID to deliver to user.
|
||||
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
|
||||
};
|
||||
|
||||
struct ROSE_STRUCT_CHECK_EXHAUSTED {
|
||||
u8 code; //!< From enum RoseInstructionCode.
|
||||
u32 ekey; //!< Exhaustion key to check.
|
||||
|
Loading…
x
Reference in New Issue
Block a user