mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2026-01-02 06:34:41 +03:00
Rose: move more report handling work into program
Move report preconditions (bounds, exhaustion, etc) into program instructions and use a more direct path to the user match callback than the adaptor functions. Report handling has been moved to new file src/report.h. Reporting from EOD now uses the same instructions as normal report handling, rather than its own. Jump target tracking in rose_build_bytecode.cpp has been cleaned up.
This commit is contained in:
committed by
Matthew Barr
parent
94b33421ca
commit
060defe6c4
@@ -34,6 +34,7 @@
|
||||
#include "infix.h"
|
||||
#include "match.h"
|
||||
#include "miracle.h"
|
||||
#include "report.h"
|
||||
#include "rose.h"
|
||||
#include "rose_internal.h"
|
||||
#include "rose_program.h"
|
||||
@@ -566,29 +567,20 @@ void roseTriggerInfix(const struct RoseEngine *t, u64a start, u64a end, u32 qi,
|
||||
pushQueueSom(q, topEvent, loc, start);
|
||||
}
|
||||
|
||||
/* handles the firing of external matches */
|
||||
static rose_inline
|
||||
hwlmcb_rv_t roseHandleMatch(const struct RoseEngine *t, char *state,
|
||||
ReportID id, u64a end, struct RoseContext *tctxt,
|
||||
char in_anchored) {
|
||||
struct hs_scratch *scratch = tctxtToScratch(tctxt);
|
||||
hwlmcb_rv_t roseReport(const struct RoseEngine *t, struct hs_scratch *scratch,
|
||||
ReportID id, u64a end, char is_exhaustible) {
|
||||
assert(end == scratch->tctxt.minMatchOffset);
|
||||
DEBUG_PRINTF("firing callback id=%u, end=%llu\n", id, end);
|
||||
updateLastMatchOffset(&scratch->tctxt, end);
|
||||
|
||||
if (roseCatchUpTo(t, state, end, scratch, in_anchored)
|
||||
== HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
|
||||
assert(end == tctxt->minMatchOffset);
|
||||
DEBUG_PRINTF("firing callback reportId=%u, end=%llu\n", id, end);
|
||||
updateLastMatchOffset(tctxt, end);
|
||||
|
||||
int cb_rv = tctxt->cb(end, id, scratch);
|
||||
int cb_rv = roseDeliverReport(end, id, scratch, is_exhaustible);
|
||||
if (cb_rv == MO_HALT_MATCHING) {
|
||||
DEBUG_PRINTF("termination requested\n");
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
|
||||
if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
|
||||
if (!is_exhaustible || cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
@@ -613,76 +605,38 @@ hwlmcb_rv_t roseCatchUpAndHandleChainMatch(const struct RoseEngine *t,
|
||||
return roseHandleChainMatch(t, r, end, tctxt, in_anchored, 0);
|
||||
}
|
||||
|
||||
static rose_inline
|
||||
hwlmcb_rv_t roseSomCatchup(const struct RoseEngine *t, char *state, u64a end,
|
||||
struct RoseContext *tctxt, char in_anchored) {
|
||||
struct hs_scratch *scratch = tctxtToScratch(tctxt);
|
||||
|
||||
// In SOM processing, we may be able to limit or entirely avoid catchup.
|
||||
|
||||
DEBUG_PRINTF("entry\n");
|
||||
|
||||
if (end == tctxt->minMatchOffset) {
|
||||
DEBUG_PRINTF("already caught up\n");
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("catching up all NFAs\n");
|
||||
if (roseCatchUpTo(t, state, end, scratch, in_anchored)
|
||||
== HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
updateMinMatchOffset(tctxt, end);
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
static really_inline
|
||||
hwlmcb_rv_t roseHandleSom(const struct RoseEngine *t, char *state, ReportID id,
|
||||
u64a end, struct RoseContext *tctxt,
|
||||
char in_anchored) {
|
||||
struct hs_scratch *scratch = tctxtToScratch(tctxt);
|
||||
|
||||
void roseHandleSom(const struct RoseEngine *t, struct hs_scratch *scratch,
|
||||
ReportID id, u64a end) {
|
||||
DEBUG_PRINTF("id=%u, end=%llu, minMatchOffset=%llu\n", id, end,
|
||||
tctxt->minMatchOffset);
|
||||
scratch->tctxt.minMatchOffset);
|
||||
|
||||
// Reach into reports and handle internal reports that just manipulate SOM
|
||||
// slots ourselves, rather than going through the callback.
|
||||
|
||||
if (roseSomCatchup(t, state, end, tctxt, in_anchored)
|
||||
== HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
assert(end == scratch->tctxt.minMatchOffset);
|
||||
DEBUG_PRINTF("firing som callback id=%u, end=%llu\n", id, end);
|
||||
updateLastMatchOffset(&scratch->tctxt, end);
|
||||
|
||||
const struct internal_report *ri = getInternalReport(t, id);
|
||||
handleSomInternal(scratch, ri, end);
|
||||
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
static rose_inline
|
||||
hwlmcb_rv_t roseHandleSomMatch(const struct RoseEngine *t, char *state,
|
||||
ReportID id, u64a start, u64a end,
|
||||
struct RoseContext *tctxt, char in_anchored) {
|
||||
struct hs_scratch *scratch = tctxtToScratch(tctxt);
|
||||
hwlmcb_rv_t roseReportSom(const struct RoseEngine *t,
|
||||
struct hs_scratch *scratch, ReportID id, u64a start,
|
||||
u64a end, char is_exhaustible) {
|
||||
assert(end == scratch->tctxt.minMatchOffset);
|
||||
DEBUG_PRINTF("firing som callback id=%u, end=%llu\n", id, end);
|
||||
updateLastMatchOffset(&scratch->tctxt, end);
|
||||
|
||||
if (roseCatchUpTo(t, state, end, scratch, in_anchored)
|
||||
== HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF("firing som callback reportId=%u, start=%llu end=%llu\n", id,
|
||||
start, end);
|
||||
DEBUG_PRINTF(" last match %llu\n", tctxt->lastMatchOffset);
|
||||
assert(end == tctxt->minMatchOffset);
|
||||
|
||||
updateLastMatchOffset(tctxt, end);
|
||||
int cb_rv = tctxt->cb_som(start, end, id, scratch);
|
||||
int cb_rv = roseDeliverSomReport(start, end, id, scratch, is_exhaustible);
|
||||
if (cb_rv == MO_HALT_MATCHING) {
|
||||
DEBUG_PRINTF("termination requested\n");
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
|
||||
if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
|
||||
if (!is_exhaustible || cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
}
|
||||
|
||||
@@ -690,23 +644,19 @@ hwlmcb_rv_t roseHandleSomMatch(const struct RoseEngine *t, char *state,
|
||||
}
|
||||
|
||||
static rose_inline
|
||||
hwlmcb_rv_t roseHandleSomSom(const struct RoseEngine *t, char *state,
|
||||
ReportID id, u64a start, u64a end,
|
||||
struct RoseContext *tctxt, char in_anchored) {
|
||||
void roseHandleSomSom(const struct RoseEngine *t, ReportID id, u64a start,
|
||||
u64a end, struct hs_scratch *scratch) {
|
||||
DEBUG_PRINTF("id=%u, start=%llu, end=%llu, minMatchOffset=%llu\n",
|
||||
id, start, end, tctxt->minMatchOffset);
|
||||
id, start, end, scratch->tctxt.minMatchOffset);
|
||||
|
||||
// Reach into reports and handle internal reports that just manipulate SOM
|
||||
// slots ourselves, rather than going through the callback.
|
||||
|
||||
if (roseSomCatchup(t, state, end, tctxt, in_anchored)
|
||||
== HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
assert(end == scratch->tctxt.minMatchOffset);
|
||||
updateLastMatchOffset(&scratch->tctxt, end);
|
||||
|
||||
const struct internal_report *ri = getInternalReport(t, id);
|
||||
setSomFromSomAware(tctxtToScratch(tctxt), ri, start, end);
|
||||
return HWLM_CONTINUE_MATCHING;
|
||||
setSomFromSomAware(scratch, ri, start, end);
|
||||
}
|
||||
|
||||
static really_inline
|
||||
@@ -848,14 +798,11 @@ u64a roseGetHaigSom(const struct RoseEngine *t, const u32 qi,
|
||||
}
|
||||
|
||||
static rose_inline
|
||||
char roseCheckRootBounds(u64a end, u32 min_bound, u32 max_bound) {
|
||||
assert(max_bound <= ROSE_BOUND_INF);
|
||||
char roseCheckBounds(u64a end, u64a min_bound, u64a max_bound) {
|
||||
DEBUG_PRINTF("check offset=%llu against bounds [%llu,%llu]\n", end,
|
||||
min_bound, max_bound);
|
||||
assert(min_bound <= max_bound);
|
||||
|
||||
if (end < min_bound) {
|
||||
return 0;
|
||||
}
|
||||
return max_bound == ROSE_BOUND_INF || end <= max_bound;
|
||||
return end >= min_bound && end <= max_bound;
|
||||
}
|
||||
|
||||
|
||||
@@ -956,9 +903,8 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, u32 programOffset,
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(CHECK_BOUNDS) {
|
||||
if (!in_anchored &&
|
||||
!roseCheckRootBounds(end, ri->min_bound, ri->max_bound)) {
|
||||
DEBUG_PRINTF("failed root bounds check\n");
|
||||
if (!roseCheckBounds(end, ri->min_bound, ri->max_bound)) {
|
||||
DEBUG_PRINTF("failed bounds check\n");
|
||||
assert(ri->fail_jump); // must progress
|
||||
pc += ri->fail_jump;
|
||||
continue;
|
||||
@@ -1003,6 +949,14 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, u32 programOffset,
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(CATCH_UP) {
|
||||
if (roseCatchUpTo(t, scratch->core_info.state, end, scratch,
|
||||
in_anchored) == HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(SOM_ADJUST) {
|
||||
assert(ri->distance <= end);
|
||||
som = end - ri->distance;
|
||||
@@ -1016,6 +970,20 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, u32 programOffset,
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(SOM_FROM_REPORT) {
|
||||
const struct internal_report *ir =
|
||||
getInternalReport(t, ri->report);
|
||||
som = handleSomExternal(scratch, ir, end);
|
||||
DEBUG_PRINTF("som from report %u is %llu\n", ri->report, som);
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(SOM_ZERO) {
|
||||
DEBUG_PRINTF("setting SOM to zero\n");
|
||||
som = 0;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(TRIGGER_INFIX) {
|
||||
roseTriggerInfix(t, som, end, ri->queue, ri->event, ri->cancel,
|
||||
tctxt);
|
||||
@@ -1033,13 +1001,40 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, u32 programOffset,
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT) {
|
||||
if (roseHandleMatch(t, scratch->core_info.state,
|
||||
ri->report, end, tctxt,
|
||||
in_anchored) == HWLM_TERMINATE_MATCHING) {
|
||||
PROGRAM_CASE(DEDUPE) {
|
||||
const struct internal_report *ir =
|
||||
getInternalReport(t, ri->report);
|
||||
const char do_som = t->hasSom; // FIXME: constant propagate
|
||||
enum DedupeResult rv = dedupeCatchup(
|
||||
t, ir, scratch, end, som, end + ir->offsetAdjust, do_som);
|
||||
switch (rv) {
|
||||
case DEDUPE_HALT:
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
case DEDUPE_SKIP:
|
||||
assert(ri->fail_jump); // must progress
|
||||
pc += ri->fail_jump;
|
||||
continue;
|
||||
case DEDUPE_CONTINUE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(DEDUPE_SOM) {
|
||||
const struct internal_report *ir =
|
||||
getInternalReport(t, ri->report);
|
||||
enum DedupeResult rv = dedupeCatchupSom(
|
||||
t, ir, scratch, end, som, end + ir->offsetAdjust);
|
||||
switch (rv) {
|
||||
case DEDUPE_HALT:
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
case DEDUPE_SKIP:
|
||||
assert(ri->fail_jump); // must progress
|
||||
pc += ri->fail_jump;
|
||||
continue;
|
||||
case DEDUPE_CONTINUE:
|
||||
break;
|
||||
}
|
||||
work_done = 1;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
@@ -1053,18 +1048,32 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, u32 programOffset,
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT_EOD) {
|
||||
if (tctxt->cb(end, ri->report, scratch) == MO_HALT_MATCHING) {
|
||||
PROGRAM_CASE(REPORT_SOM_INT) {
|
||||
roseHandleSom(t, scratch, ri->report, end);
|
||||
work_done = 1;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT_SOM_AWARE) {
|
||||
roseHandleSomSom(t, ri->report, som, end, scratch);
|
||||
work_done = 1;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT) {
|
||||
const char is_exhaustible = 0;
|
||||
if (roseReport(t, scratch, ri->report, end, is_exhaustible) ==
|
||||
HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
work_done = 1;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT_SOM_INT) {
|
||||
if (roseHandleSom(t, scratch->core_info.state, ri->report,
|
||||
end, tctxt,
|
||||
in_anchored) == HWLM_TERMINATE_MATCHING) {
|
||||
PROGRAM_CASE(REPORT_EXHAUST) {
|
||||
const char is_exhaustible = 1;
|
||||
if (roseReport(t, scratch, ri->report, end, is_exhaustible) ==
|
||||
HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
work_done = 1;
|
||||
@@ -1072,25 +1081,57 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, u32 programOffset,
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT_SOM) {
|
||||
if (roseHandleSomSom(t, scratch->core_info.state,
|
||||
ri->report, som, end, tctxt,
|
||||
in_anchored) == HWLM_TERMINATE_MATCHING) {
|
||||
const char is_exhaustible = 0;
|
||||
if (roseReportSom(t, scratch, ri->report, som, end,
|
||||
is_exhaustible) == HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
work_done = 1;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(REPORT_SOM_KNOWN) {
|
||||
if (roseHandleSomMatch(t, scratch->core_info.state, ri->report,
|
||||
som, end, tctxt, in_anchored) ==
|
||||
HWLM_TERMINATE_MATCHING) {
|
||||
PROGRAM_CASE(REPORT_SOM_EXHAUST) {
|
||||
const char is_exhaustible = 1;
|
||||
if (roseReportSom(t, scratch, ri->report, som, end,
|
||||
is_exhaustible) == HWLM_TERMINATE_MATCHING) {
|
||||
return HWLM_TERMINATE_MATCHING;
|
||||
}
|
||||
work_done = 1;
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(CHECK_EXHAUSTED) {
|
||||
DEBUG_PRINTF("check ekey %u\n", ri->ekey);
|
||||
assert(ri->ekey != INVALID_EKEY);
|
||||
assert(ri->ekey < t->ekeyCount);
|
||||
const char *evec = scratch->core_info.exhaustionVector;
|
||||
if (isExhausted(evec, ri->ekey)) {
|
||||
DEBUG_PRINTF("ekey %u already set, match is exhausted\n",
|
||||
ri->ekey);
|
||||
assert(ri->fail_jump); // must progress
|
||||
pc += ri->fail_jump;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(CHECK_MIN_LENGTH) {
|
||||
DEBUG_PRINTF("check min length %llu (adj %d)\n", ri->min_length,
|
||||
ri->end_adj);
|
||||
assert(ri->min_length > 0);
|
||||
assert(ri->end_adj == 0 || ri->end_adj == -1);
|
||||
assert(som == HS_OFFSET_PAST_HORIZON || som <= end);
|
||||
if (som != HS_OFFSET_PAST_HORIZON &&
|
||||
((end + ri->end_adj) - som < ri->min_length)) {
|
||||
DEBUG_PRINTF("failed check, match len %llu\n",
|
||||
(u64a)((end + ri->end_adj) - som));
|
||||
assert(ri->fail_jump); // must progress
|
||||
pc += ri->fail_jump;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PROGRAM_NEXT_INSTRUCTION
|
||||
|
||||
PROGRAM_CASE(SET_STATE) {
|
||||
DEBUG_PRINTF("set state index %u\n", ri->index);
|
||||
mmbit_set(getRoleState(scratch->core_info.state),
|
||||
|
||||
Reference in New Issue
Block a user