Rose: replace internal_report with program

Replace the use of the internal_report structure (for reports from
engines, MPV etc) with the Rose program interpreter.

SOM processing was reworked to use a new som_operation structure that is
embedded in the appropriate instructions.
This commit is contained in:
Justin Viiret
2016-03-22 16:45:09 +11:00
committed by Matthew Barr
parent 68851742cc
commit 36150bbc19
31 changed files with 877 additions and 1356 deletions

View File

@@ -133,7 +133,6 @@ void init_outfixes_for_block(const struct RoseEngine *t,
static really_inline
void init_for_block(const struct RoseEngine *t, struct hs_scratch *scratch,
RoseCallback callback, RoseCallbackSom som_callback,
char *state, char is_small_block) {
init_state_for_block(t, state);
@@ -144,8 +143,6 @@ void init_for_block(const struct RoseEngine *t, struct hs_scratch *scratch,
tctxt->delayLastEndOffset = 0;
tctxt->lastEndOffset = 0;
tctxt->filledDelayedSlots = 0;
tctxt->cb = callback;
tctxt->cb_som = som_callback;
tctxt->lastMatchOffset = 0;
tctxt->minMatchOffset = 0;
tctxt->minNonMpvMatchOffset = 0;
@@ -160,8 +157,7 @@ void init_for_block(const struct RoseEngine *t, struct hs_scratch *scratch,
init_outfixes_for_block(t, scratch, state, is_small_block);
}
void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch,
RoseCallback callback, RoseCallbackSom som_callback) {
void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch) {
assert(t);
assert(scratch);
assert(scratch->core_info.buf);
@@ -179,8 +175,7 @@ void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch,
char *state = scratch->core_info.state;
init_for_block(t, scratch, callback, som_callback, state,
is_small_block);
init_for_block(t, scratch, state, is_small_block);
struct RoseContext *tctxt = &scratch->tctxt;

View File

@@ -33,6 +33,7 @@
#include "catchup.h"
#include "match.h"
#include "program_runtime.h"
#include "rose.h"
#include "nfa/nfa_rev_api.h"
#include "nfa/mpv.h"
@@ -46,43 +47,18 @@ typedef struct queue_match PQ_T;
#include "util/pqueue.h"
static really_inline
int handleReportInternally(const struct RoseEngine *t,
struct hs_scratch *scratch, ReportID id,
u64a offset) {
const struct internal_report *ri = getInternalReport(t, id);
if (ri->type == EXTERNAL_CALLBACK) {
return 0;
}
if (isInternalSomReport(ri)) {
handleSomInternal(scratch, ri, offset);
return 1;
}
if (ri->type == INTERNAL_ROSE_CHAIN) {
roseHandleChainMatch(t, scratch, id, offset, 1);
return 1;
}
int roseNfaRunProgram(const struct RoseEngine *rose, struct hs_scratch *scratch,
u64a som, u64a offset, ReportID id, const char from_mpv) {
assert(id < rose->reportProgramCount);
const u32 *programs = getByOffset(rose, rose->reportProgramOffset);
return 0;
}
const size_t match_len = 0; // Unused in this path.
const char in_anchored = 0;
const char in_catchup = 1;
roseRunProgram(rose, scratch, programs[id], som, offset, match_len,
in_anchored, in_catchup, from_mpv, 0);
static really_inline
int handleReportInternallyNoChain(const struct RoseEngine *t,
struct hs_scratch *scratch, ReportID id,
u64a offset) {
const struct internal_report *ri = getInternalReport(t, id);
if (ri->type == EXTERNAL_CALLBACK) {
return 0;
}
if (isInternalSomReport(ri)) {
handleSomInternal(scratch, ri, offset);
return 1;
}
if (ri->type == INTERNAL_ROSE_CHAIN) {
assert(0); /* chained engines cannot trigger other engines */
return 1;
}
return 0;
return can_stop_matching(scratch) ? MO_HALT_MATCHING : MO_CONTINUE_MATCHING;
}
static really_inline
@@ -270,50 +246,15 @@ restart:
}
/* for use by mpv (chained) only */
static UNUSED
static
int roseNfaFinalBlastAdaptor(u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
DEBUG_PRINTF("called\n");
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
updateLastMatchOffset(tctxt, offset);
if (handleReportInternallyNoChain(t, scratch, id, offset)) {
return MO_CONTINUE_MATCHING;
}
int cb_rv = tctxt->cb(offset, id, scratch);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
return MO_CONTINUE_MATCHING;
} else {
assert(cb_rv == MO_CONTINUE_MATCHING);
return !roseSuffixIsExhausted(t, 0,
scratch->core_info.exhaustionVector);
}
}
/* for use by mpv (chained) only */
static UNUSED
int roseNfaFinalBlastAdaptorNoInternal(u64a offset, ReportID id,
void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
DEBUG_PRINTF("called\n");
/* chained nfas are run under the control of the anchored catchup */
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
updateLastMatchOffset(tctxt, offset);
int cb_rv = tctxt->cb(offset, id, scratch);
int cb_rv = roseNfaRunProgram(t, scratch, 0, offset, id, 1);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
@@ -418,11 +359,7 @@ hwlmcb_rv_t roseCatchUpMPV_i(const struct RoseEngine *t, s64a loc,
assert(!q->report_current);
if (info->only_external) {
q->cb = roseNfaFinalBlastAdaptorNoInternal;
} else {
q->cb = roseNfaFinalBlastAdaptor;
}
q->cb = roseNfaFinalBlastAdaptor;
q->som_cb = NULL;
DEBUG_PRINTF("queue %u blasting, %u/%u [%lld/%lld]\n",
@@ -466,35 +403,28 @@ done:
: HWLM_CONTINUE_MATCHING;
}
static UNUSED
static really_inline
char in_mpv(const struct RoseEngine *rose, const struct hs_scratch *scratch) {
const struct RoseContext *tctxt = &scratch->tctxt;
assert(tctxt->curr_qi < rose->queueCount);
if (tctxt->curr_qi < rose->outfixBeginQueue) {
assert(getNfaByQueue(rose, tctxt->curr_qi)->type == MPV_NFA_0);
return 1;
}
return 0;
}
static
int roseNfaBlastAdaptor(u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
const struct internal_report *ri = getInternalReport(t, id);
DEBUG_PRINTF("called\n");
if (ri->type != INTERNAL_ROSE_CHAIN) {
/* INTERNAL_ROSE_CHAIN are not visible externally */
if (roseCatchUpMPV(t, offset - scratch->core_info.buf_offset,
scratch) == HWLM_TERMINATE_MATCHING) {
DEBUG_PRINTF("done\n");
return MO_HALT_MATCHING;
}
}
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
if (handleReportInternally(t, scratch, id, offset)) {
return can_stop_matching(scratch) ? MO_HALT_MATCHING
: MO_CONTINUE_MATCHING;
}
updateLastMatchOffset(tctxt, offset);
int cb_rv = tctxt->cb(offset, id, scratch);
const char from_mpv = in_mpv(t, scratch);
int cb_rv = roseNfaRunProgram(t, scratch, 0, offset, id, from_mpv);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
@@ -506,24 +436,18 @@ int roseNfaBlastAdaptor(u64a offset, ReportID id, void *context) {
}
}
static UNUSED
static
int roseNfaBlastAdaptorNoInternal(u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
DEBUG_PRINTF("called\n");
if (roseCatchUpMPV(t, offset - scratch->core_info.buf_offset, scratch) ==
HWLM_TERMINATE_MATCHING) {
DEBUG_PRINTF("done\n");
return MO_HALT_MATCHING;
}
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
updateLastMatchOffset(tctxt, offset);
int cb_rv = tctxt->cb(offset, id, scratch);
assert(!in_mpv(t, scratch));
int cb_rv = roseNfaRunProgram(t, scratch, 0, offset, id, 0);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
@@ -535,78 +459,21 @@ int roseNfaBlastAdaptorNoInternal(u64a offset, ReportID id, void *context) {
}
}
static UNUSED
int roseNfaBlastAdaptorNoChain(u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
updateLastMatchOffset(tctxt, offset);
if (handleReportInternallyNoChain(t, scratch, id, offset)) {
return MO_CONTINUE_MATCHING;
}
int cb_rv = tctxt->cb(offset, id, scratch);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
return MO_CONTINUE_MATCHING;
} else {
assert(cb_rv == MO_CONTINUE_MATCHING);
return !roseSuffixIsExhausted(t, tctxt->curr_qi,
scratch->core_info.exhaustionVector);
}
}
static UNUSED
int roseNfaBlastAdaptorNoInternalNoChain(u64a offset, ReportID id,
void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
/* chained nfas are run under the control of the anchored catchup */
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
updateLastMatchOffset(tctxt, offset);
int cb_rv = tctxt->cb(offset, id, scratch);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
return MO_CONTINUE_MATCHING;
} else {
assert(cb_rv == MO_CONTINUE_MATCHING);
return !roseSuffixIsExhausted(t, tctxt->curr_qi,
scratch->core_info.exhaustionVector);
}
}
static UNUSED
static
int roseNfaBlastSomAdaptor(u64a from_offset, u64a offset, ReportID id,
void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
const struct RoseEngine *t = scratch->core_info.rose;
DEBUG_PRINTF("called\n");
if (roseCatchUpMPV(t, offset - scratch->core_info.buf_offset, scratch) ==
HWLM_TERMINATE_MATCHING) {
DEBUG_PRINTF("roseCatchUpNfas done\n");
return MO_HALT_MATCHING;
}
DEBUG_PRINTF("masky got himself a blasted match @%llu id %u !woot!\n",
offset, id);
updateLastMatchOffset(tctxt, offset);
assert(!in_mpv(t, scratch));
/* must be a external report as haig cannot directly participate in chain */
int cb_rv = tctxt->cb_som(from_offset, offset, id, scratch);
int cb_rv = roseNfaRunProgram(scratch->core_info.rose, scratch, from_offset,
offset, id, 0);
if (cb_rv == MO_HALT_MATCHING) {
return MO_HALT_MATCHING;
} else if (cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
@@ -620,38 +487,20 @@ int roseNfaBlastSomAdaptor(u64a from_offset, u64a offset, ReportID id,
int roseNfaAdaptor(u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
DEBUG_PRINTF("masky got himself a match @%llu id %u !woot!\n", offset, id);
updateLastMatchOffset(tctxt, offset);
const struct RoseEngine *t = scratch->core_info.rose;
if (handleReportInternally(t, scratch, id, offset)) {
return can_stop_matching(scratch) ? MO_HALT_MATCHING
: MO_CONTINUE_MATCHING;
}
return tctxt->cb(offset, id, scratch);
}
int roseNfaAdaptorNoInternal(u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
DEBUG_PRINTF("masky got himself a match @%llu id %u !woot!\n", offset, id);
updateLastMatchOffset(tctxt, offset);
return tctxt->cb(offset, id, scratch);
return roseNfaRunProgram(scratch->core_info.rose, scratch, 0, offset, id,
0);
}
int roseNfaSomAdaptor(u64a from_offset, u64a offset, ReportID id,
void *context) {
struct hs_scratch *scratch = context;
struct RoseContext *tctxt = &scratch->tctxt;
DEBUG_PRINTF("masky got himself a match @%llu id %u !woot!\n", offset, id);
updateLastMatchOffset(tctxt, offset);
/* must be a external report as haig cannot directly participate in chain */
return tctxt->cb_som(from_offset, offset, id, scratch);
return roseNfaRunProgram(scratch->core_info.rose, scratch, from_offset,
offset, id, 0);
}
static really_inline
@@ -661,29 +510,17 @@ char blast_queue(const struct RoseEngine *t, struct hs_scratch *scratch,
const struct NfaInfo *info = getNfaInfoByQueue(t, qi);
tctxt->curr_qi = qi;
if (has_chained_nfas(t)) {
if (info->only_external) {
q->cb = roseNfaBlastAdaptorNoInternal;
} else {
q->cb = roseNfaBlastAdaptor;
}
if (info->only_external) {
q->cb = roseNfaBlastAdaptorNoInternal;
} else {
if (info->only_external) {
q->cb = roseNfaBlastAdaptorNoInternalNoChain;
} else {
q->cb = roseNfaBlastAdaptorNoChain;
}
q->cb = roseNfaBlastAdaptor;
}
q->report_current = report_current;
q->som_cb = roseNfaBlastSomAdaptor;
DEBUG_PRINTF("queue %u blasting, %u/%u [%lld/%lld]\n", qi, q->cur, q->end,
q_cur_loc(q), to_loc);
char alive = nfaQueueExec(q->nfa, q, to_loc);
if (info->only_external) {
q->cb = roseNfaAdaptorNoInternal;
} else {
q->cb = roseNfaAdaptor;
}
q->cb = roseNfaAdaptor;
q->som_cb = roseNfaSomAdaptor;
assert(!q->report_current);
@@ -945,14 +782,16 @@ hwlmcb_rv_t buildSufPQ(const struct RoseEngine *t, char *state, s64a safe_loc,
static never_inline
hwlmcb_rv_t roseCatchUpNfas(const struct RoseEngine *t, s64a loc,
s64a final_loc, struct hs_scratch *scratch) {
struct RoseContext *tctxt = &scratch->tctxt;
assert(t->activeArrayCount);
assert(scratch->core_info.buf_offset + loc >= tctxt->minNonMpvMatchOffset);
DEBUG_PRINTF("roseCatchUpNfas %lld/%lld\n", loc, final_loc);
DEBUG_PRINTF("roseCatchUpNfas offset=%llu + %lld/%lld\n",
scratch->core_info.buf_offset, loc, final_loc);
DEBUG_PRINTF("min non mpv match offset %llu\n",
scratch->tctxt.minNonMpvMatchOffset);
struct RoseContext *tctxt = &scratch->tctxt;
assert(scratch->core_info.buf_offset + loc >= tctxt->minNonMpvMatchOffset);
char *state = scratch->core_info.state;
struct mq *queues = scratch->queues;
u8 *aa = getActiveLeafArray(t, state);

View File

@@ -56,9 +56,6 @@
#include "ue2common.h"
#include "util/multibit.h"
/* Callbacks, defined in catchup.c */
hwlmcb_rv_t roseCatchUpAll(s64a loc, struct hs_scratch *scratch);
/* will only catch mpv up to last reported external match */

View File

@@ -34,8 +34,7 @@
static really_inline
void initContext(const struct RoseEngine *t, char *state, u64a offset,
struct hs_scratch *scratch, RoseCallback callback,
RoseCallbackSom som_callback) {
struct hs_scratch *scratch) {
struct RoseContext *tctxt = &scratch->tctxt;
tctxt->groups = loadGroups(t, state); /* TODO: diff groups for eod */
tctxt->lit_offset_adjust = scratch->core_info.buf_offset
@@ -44,8 +43,6 @@ void initContext(const struct RoseEngine *t, char *state, u64a offset,
tctxt->delayLastEndOffset = offset;
tctxt->lastEndOffset = offset;
tctxt->filledDelayedSlots = 0;
tctxt->cb = callback;
tctxt->cb_som = som_callback;
tctxt->lastMatchOffset = 0;
tctxt->minMatchOffset = offset;
tctxt->minNonMpvMatchOffset = offset;
@@ -109,38 +106,21 @@ int roseEodRunIterator(const struct RoseEngine *t, u64a offset,
DEBUG_PRINTF("running eod program at offset %u\n", t->eodIterProgramOffset);
const u64a som = 0;
const size_t match_len = 0;
if (roseRunProgram(t, scratch, t->eodIterProgramOffset, offset, match_len,
0) == HWLM_TERMINATE_MATCHING) {
const char in_anchored = 0;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 1;
if (roseRunProgram(t, scratch, t->eodIterProgramOffset, som, offset,
match_len, in_anchored, in_catchup,
from_mpv, skip_mpv_catchup) == HWLM_TERMINATE_MATCHING) {
return MO_HALT_MATCHING;
}
return MO_CONTINUE_MATCHING;
}
/**
* \brief Adapts an NfaCallback to the rose callback specified in the
* RoseContext.
*/
static
int eodNfaCallback(u64a offset, ReportID report, void *context) {
struct hs_scratch *scratch = context;
assert(scratch->magic == SCRATCH_MAGIC);
return scratch->tctxt.cb(offset, report, scratch);
}
/**
* \brief Adapts a SomNfaCallback to the rose SOM callback specified in the
* RoseContext.
*/
static
int eodNfaSomCallback(u64a from_offset, u64a to_offset, ReportID report,
void *context) {
struct hs_scratch *scratch = context;
assert(scratch->magic == SCRATCH_MAGIC);
return scratch->tctxt.cb_som(from_offset, to_offset, report, scratch);
}
/**
* \brief Check for (and deliver) reports from active output-exposed (suffix
* or outfix) NFAs.
@@ -190,8 +170,8 @@ int roseCheckNfaEod(const struct RoseEngine *t, char *state,
nfaExpandState(nfa, fstate, sstate, offset, key);
}
if (nfaCheckFinalState(nfa, fstate, sstate, offset, eodNfaCallback,
eodNfaSomCallback,
if (nfaCheckFinalState(nfa, fstate, sstate, offset, roseReportAdaptor,
roseReportSomAdaptor,
scratch) == MO_HALT_MATCHING) {
DEBUG_PRINTF("user instructed us to stop\n");
return MO_HALT_MATCHING;
@@ -239,8 +219,8 @@ void roseCheckEodSuffixes(const struct RoseEngine *t, char *state, u64a offset,
* history buffer. */
char rv = nfaQueueExecRose(q->nfa, q, MO_INVALID_IDX);
if (rv) { /* nfa is still alive */
if (nfaCheckFinalState(nfa, fstate, sstate, offset, eodNfaCallback,
eodNfaSomCallback,
if (nfaCheckFinalState(nfa, fstate, sstate, offset,
roseReportAdaptor, roseReportSomAdaptor,
scratch) == MO_HALT_MATCHING) {
DEBUG_PRINTF("user instructed us to stop\n");
return;
@@ -261,9 +241,15 @@ int roseRunEodProgram(const struct RoseEngine *t, u64a offset,
// There should be no pending delayed literals.
assert(!scratch->tctxt.filledDelayedSlots);
const u64a som = 0;
const size_t match_len = 0;
if (roseRunProgram(t, scratch, t->eodProgramOffset, offset, match_len, 0) ==
HWLM_TERMINATE_MATCHING) {
const char in_anchored = 0;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 1;
if (roseRunProgram(t, scratch, t->eodProgramOffset, som, offset, match_len,
in_anchored, in_catchup, from_mpv,
skip_mpv_catchup) == HWLM_TERMINATE_MATCHING) {
return MO_HALT_MATCHING;
}
@@ -322,10 +308,8 @@ void roseEodExec_i(const struct RoseEngine *t, char *state, u64a offset,
}
void roseEodExec(const struct RoseEngine *t, u64a offset,
struct hs_scratch *scratch, RoseCallback callback,
RoseCallbackSom som_callback) {
struct hs_scratch *scratch) {
assert(scratch);
assert(callback);
assert(t->requiresEodCheck);
DEBUG_PRINTF("ci buf %p/%zu his %p/%zu\n", scratch->core_info.buf,
scratch->core_info.len, scratch->core_info.hbuf,
@@ -345,7 +329,7 @@ void roseEodExec(const struct RoseEngine *t, u64a offset,
char *state = scratch->core_info.state;
assert(state);
initContext(t, state, offset, scratch, callback, som_callback);
initContext(t, state, offset, scratch);
roseEodExec_i(t, state, offset, scratch, 1);
}

View File

@@ -96,9 +96,15 @@ hwlmcb_rv_t roseDelayRebuildCallback(size_t start, size_t end, u32 id,
const u32 program = delayRebuildPrograms[id];
if (program) {
const u64a som = 0;
const size_t match_len = end - start + 1;
const char in_anchored = 0;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 0;
UNUSED hwlmcb_rv_t rv =
roseRunProgram(t, scratch, program, real_end, match_len, 0);
roseRunProgram(t, scratch, program, som, real_end, match_len,
in_anchored, in_catchup, from_mpv, skip_mpv_catchup);
assert(rv != HWLM_TERMINATE_MATCHING);
}
@@ -138,8 +144,10 @@ void recordAnchoredLiteralMatch(const struct RoseEngine *t,
}
hwlmcb_rv_t roseHandleChainMatch(const struct RoseEngine *t,
struct hs_scratch *scratch, ReportID r,
u64a end, char in_catchup) {
struct hs_scratch *scratch, u32 event,
u64a top_squash_distance, u64a end,
char in_catchup) {
assert(event == MQE_TOP || event >= MQE_TOP_FIRST);
struct core_info *ci = &scratch->core_info;
u8 *aa = getActiveLeafArray(t, scratch->core_info.state);
@@ -147,18 +155,7 @@ hwlmcb_rv_t roseHandleChainMatch(const struct RoseEngine *t,
struct fatbit *activeQueues = scratch->aqa;
u32 qCount = t->queueCount;
const struct internal_report *ri = getInternalReport(t, r);
assert(ri->type == INTERNAL_ROSE_CHAIN);
u32 qi = 0; /* MPV is always queue 0 if it exists */
u32 event = ri->onmatch;
assert(event == MQE_TOP || event >= MQE_TOP_FIRST);
/* TODO: populate INTERNAL_ROSE_CHAIN internal reports with offset where
* possible */
if (end < ri->minOffset || (ri->maxOffset && end > ri->maxOffset)) {
return HWLM_CONTINUE_MATCHING;
}
const u32 qi = 0; /* MPV is always queue 0 if it exists */
struct mq *q = &scratch->queues[qi];
const struct NfaInfo *info = getNfaInfoByQueue(t, qi);
@@ -189,11 +186,11 @@ hwlmcb_rv_t roseHandleChainMatch(const struct RoseEngine *t,
}
}
if (ri->aux.topSquashDistance) {
if (top_squash_distance) {
assert(q->cur != q->end);
struct mq_item *last = &q->items[q->end - 1];
if (last->type == event
&& last->location >= loc - (s64a)ri->aux.topSquashDistance) {
&& last->location >= loc - (s64a)top_squash_distance) {
last->location = loc;
goto event_enqueued;
}
@@ -255,8 +252,14 @@ int roseAnchoredCallback(u64a end, u32 id, void *ctx) {
const u32 *programs = getByOffset(t, t->litProgramOffset);
assert(id < t->literalCount);
if (roseRunProgram(t, scratch, programs[id], real_end, match_len, 1) ==
HWLM_TERMINATE_MATCHING) {
const u64a som = 0;
const char in_anchored = 1;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 0;
if (roseRunProgram(t, scratch, programs[id], som, real_end, match_len,
in_anchored, in_catchup, from_mpv,
skip_mpv_catchup) == HWLM_TERMINATE_MATCHING) {
assert(can_stop_matching(scratch));
DEBUG_PRINTF("caller requested termination\n");
return MO_HALT_MATCHING;
@@ -280,7 +283,13 @@ hwlmcb_rv_t roseProcessMatch(const struct RoseEngine *t,
DEBUG_PRINTF("id=%u\n", id);
const u32 *programs = getByOffset(t, t->litProgramOffset);
assert(id < t->literalCount);
return roseRunProgram(t, scratch, programs[id], end, match_len, 0);
const u64a som = 0;
const char in_anchored = 0;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 0;
return roseRunProgram(t, scratch, programs[id], som, end, match_len,
in_anchored, in_catchup, from_mpv, skip_mpv_catchup);
}
static rose_inline
@@ -568,11 +577,17 @@ hwlmcb_rv_t rosePureLiteralCallback(size_t start, size_t end, u32 id,
struct hs_scratch *scratch = context;
struct core_info *ci = &scratch->core_info;
const u64a real_end = (u64a)end + ci->buf_offset + 1;
const u64a som = 0;
const size_t match_len = end - start + 1;
const struct RoseEngine *rose = ci->rose;
const u32 *programs = getByOffset(rose, rose->litProgramOffset);
assert(id < rose->literalCount);
return roseRunProgram(rose, scratch, programs[id], real_end, match_len, 0);
const char in_anchored = 0;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 0;
return roseRunProgram(rose, scratch, programs[id], som, real_end, match_len,
in_anchored, in_catchup, from_mpv, skip_mpv_catchup);
}
/**
@@ -606,13 +621,53 @@ int roseRunBoundaryProgram(const struct RoseEngine *rose, u32 program,
// time we are running boundary report programs.
scratch->tctxt.minMatchOffset = stream_offset;
const u64a som = 0;
const size_t match_len = 0;
const char in_anchored = 0;
hwlmcb_rv_t rv = roseRunProgram(rose, scratch, program, stream_offset,
match_len, in_anchored);
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 0;
hwlmcb_rv_t rv =
roseRunProgram(rose, scratch, program, som, stream_offset, match_len,
in_anchored, in_catchup, from_mpv, skip_mpv_catchup);
if (rv == HWLM_TERMINATE_MATCHING) {
return MO_HALT_MATCHING;
}
return MO_CONTINUE_MATCHING;
}
static really_inline
int roseReportAdaptor_i(u64a som, u64a offset, ReportID id, void *context) {
struct hs_scratch *scratch = context;
assert(scratch && scratch->magic == SCRATCH_MAGIC);
const struct RoseEngine *rose = scratch->core_info.rose;
assert(id < rose->reportProgramCount);
const u32 *programs = getByOffset(rose, rose->reportProgramOffset);
const size_t match_len = 0; // Unused in this path.
const char in_anchored = 0;
const char in_catchup = 0;
const char from_mpv = 0;
const char skip_mpv_catchup = 1;
hwlmcb_rv_t rv =
roseRunProgram(rose, scratch, programs[id], som, offset, match_len,
in_anchored, in_catchup, from_mpv, skip_mpv_catchup);
if (rv == HWLM_TERMINATE_MATCHING) {
return MO_HALT_MATCHING;
}
return can_stop_matching(scratch) ? MO_HALT_MATCHING : MO_CONTINUE_MATCHING;
}
int roseReportAdaptor(u64a offset, ReportID id, void *context) {
DEBUG_PRINTF("offset=%llu, id=%u\n", offset, id);
return roseReportAdaptor_i(0, offset, id, context);
}
int roseReportSomAdaptor(u64a som, u64a offset, ReportID id, void *context) {
DEBUG_PRINTF("som=%llu, offset=%llu, id=%u\n", som, offset, id);
return roseReportAdaptor_i(som, offset, id, context);
}

View File

@@ -41,13 +41,11 @@
#include "som/som_runtime.h"
#include "util/bitutils.h"
#include "util/fatbit.h"
#include "util/internal_report.h"
#include "util/multibit.h"
/* Callbacks, defined in catchup.c */
int roseNfaAdaptor(u64a offset, ReportID id, void *context);
int roseNfaAdaptorNoInternal(u64a offset, ReportID id, void *context);
int roseNfaSomAdaptor(u64a from_offset, u64a offset, ReportID id, void *context);
/* Callbacks, defined in match.c */
@@ -60,8 +58,9 @@ int roseAnchoredCallback(u64a end, u32 id, void *ctx);
/* Common code, used all over Rose runtime */
hwlmcb_rv_t roseHandleChainMatch(const struct RoseEngine *t,
struct hs_scratch *scratch, ReportID r,
u64a end, char in_catchup);
struct hs_scratch *scratch, u32 event,
u64a top_squash_distance, u64a end,
char in_catchup);
static really_inline
void initQueue(struct mq *q, u32 qi, const struct RoseEngine *t,
@@ -78,11 +77,7 @@ void initQueue(struct mq *q, u32 qi, const struct RoseEngine *t,
q->length = scratch->core_info.len;
q->history = scratch->core_info.hbuf;
q->hlength = scratch->core_info.hlen;
if (info->only_external) {
q->cb = roseNfaAdaptorNoInternal;
} else {
q->cb = roseNfaAdaptor;
}
q->cb = roseNfaAdaptor;
q->som_cb = roseNfaSomAdaptor;
q->context = scratch;
q->report_current = 0;

View File

@@ -573,14 +573,13 @@ void roseTriggerInfix(const struct RoseEngine *t, struct hs_scratch *scratch,
static rose_inline
hwlmcb_rv_t roseReport(const struct RoseEngine *t, struct hs_scratch *scratch,
u64a end, ReportID id, ReportID onmatch,
s32 offset_adjust, u32 ekey) {
u64a end, ReportID onmatch, s32 offset_adjust,
u32 ekey) {
assert(!t->needsCatchup || end == scratch->tctxt.minMatchOffset);
DEBUG_PRINTF("firing callback id=%u, end=%llu\n", id, end);
DEBUG_PRINTF("firing callback onmatch=%u, end=%llu\n", onmatch, end);
updateLastMatchOffset(&scratch->tctxt, end);
int cb_rv = roseDeliverReport(end, id, onmatch, offset_adjust, scratch,
ekey);
int cb_rv = roseDeliverReport(end, onmatch, offset_adjust, scratch, ekey);
if (cb_rv == MO_HALT_MATCHING) {
DEBUG_PRINTF("termination requested\n");
return HWLM_TERMINATE_MATCHING;
@@ -599,47 +598,45 @@ hwlmcb_rv_t roseReport(const struct RoseEngine *t, struct hs_scratch *scratch,
static rose_inline
hwlmcb_rv_t roseCatchUpAndHandleChainMatch(const struct RoseEngine *t,
struct hs_scratch *scratch,
ReportID r, u64a end) {
if (roseCatchUpMpvFeeders(t, scratch, end) == HWLM_TERMINATE_MATCHING) {
u32 event, u64a top_squash_distance,
u64a end, const char in_catchup) {
if (!in_catchup &&
roseCatchUpMpvFeeders(t, scratch, end) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
return roseHandleChainMatch(t, scratch, r, end, 0);
return roseHandleChainMatch(t, scratch, event, top_squash_distance, end,
in_catchup);
}
static rose_inline
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,
scratch->tctxt.minMatchOffset);
// Reach into reports and handle internal reports that just manipulate SOM
// slots ourselves, rather than going through the callback.
void roseHandleSom(UNUSED const struct RoseEngine *t,
struct hs_scratch *scratch, const struct som_operation *sr,
u64a end) {
DEBUG_PRINTF("end=%llu, minMatchOffset=%llu\n", end,
scratch->tctxt.minMatchOffset);
assert(!t->needsCatchup || 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);
handleSomInternal(scratch, sr, end);
}
static rose_inline
hwlmcb_rv_t roseReportSom(const struct RoseEngine *t,
struct hs_scratch *scratch, ReportID id, u64a start,
u64a end, char is_exhaustible) {
struct hs_scratch *scratch, u64a start, u64a end,
ReportID onmatch, s32 offset_adjust, u32 ekey) {
assert(!t->needsCatchup || end == scratch->tctxt.minMatchOffset);
DEBUG_PRINTF("firing som callback id=%u, end=%llu\n", id, end);
DEBUG_PRINTF("firing som callback onmatch=%u, start=%llu, end=%llu\n",
onmatch, start, end);
updateLastMatchOffset(&scratch->tctxt, end);
const struct internal_report *ir = getInternalReport(t, id);
int cb_rv = roseDeliverSomReport(start, end, ir, scratch, is_exhaustible);
int cb_rv = roseDeliverSomReport(start, end, onmatch, offset_adjust,
scratch, ekey);
if (cb_rv == MO_HALT_MATCHING) {
DEBUG_PRINTF("termination requested\n");
return HWLM_TERMINATE_MATCHING;
}
if (!is_exhaustible || cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
if (ekey == INVALID_EKEY || cb_rv == ROSE_CONTINUE_MATCHING_NO_EXHAUST) {
return HWLM_CONTINUE_MATCHING;
}
@@ -647,19 +644,15 @@ hwlmcb_rv_t roseReportSom(const struct RoseEngine *t,
}
static rose_inline
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, scratch->tctxt.minMatchOffset);
// Reach into reports and handle internal reports that just manipulate SOM
// slots ourselves, rather than going through the callback.
void roseHandleSomSom(UNUSED const struct RoseEngine *t,
struct hs_scratch *scratch,
const struct som_operation *sr, u64a start, u64a end) {
DEBUG_PRINTF("start=%llu, end=%llu, minMatchOffset=%llu\n", start, end,
scratch->tctxt.minMatchOffset);
assert(!t->needsCatchup || end == scratch->tctxt.minMatchOffset);
updateLastMatchOffset(&scratch->tctxt, end);
const struct internal_report *ri = getInternalReport(t, id);
setSomFromSomAware(scratch, ri, start, end);
setSomFromSomAware(scratch, sr, start, end);
}
static really_inline
@@ -807,6 +800,16 @@ char roseCheckBounds(u64a end, u64a min_bound, u64a max_bound) {
return end >= min_bound && end <= max_bound;
}
static
void updateSeqPoint(struct RoseContext *tctxt, u64a offset,
const char from_mpv) {
if (from_mpv) {
updateMinMatchOffsetFromMpv(tctxt, offset);
} else {
updateMinMatchOffset(tctxt, offset);
}
}
#define PROGRAM_CASE(name) \
case ROSE_INSTR_##name: { \
DEBUG_PRINTF("instruction: " #name " (pc=%u)\n", \
@@ -822,8 +825,10 @@ char roseCheckBounds(u64a end, u64a min_bound, u64a max_bound) {
static rose_inline
hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
struct hs_scratch *scratch, u32 programOffset,
u64a end, size_t match_len, char in_anchored) {
DEBUG_PRINTF("program begins at offset %u\n", programOffset);
u64a som, u64a end, size_t match_len,
char in_anchored, char in_catchup, char from_mpv,
char skip_mpv_catchup) {
DEBUG_PRINTF("program=%u, offsets [%llu,%llu]\n", programOffset, som, end);
assert(programOffset);
assert(programOffset < t->size);
@@ -831,8 +836,6 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
const char *pc_base = getByOffset(t, programOffset);
const char *pc = pc_base;
u64a som = 0;
// Local sparse iterator state for programs that use the SPARSE_ITER_BEGIN
// and SPARSE_ITER_NEXT instructions.
struct mmbit_sparse_state si_state[MAX_SPARSE_ITER_STATES];
@@ -972,6 +975,17 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(CATCH_UP_MPV) {
if (from_mpv || skip_mpv_catchup) {
DEBUG_PRINTF("skipping mpv catchup\n");
} else if (roseCatchUpMPV(t,
end - scratch->core_info.buf_offset,
scratch) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(SOM_ADJUST) {
assert(ri->distance <= end);
som = end - ri->distance;
@@ -986,10 +1000,9 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
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);
som = handleSomExternal(scratch, &ri->som, end);
DEBUG_PRINTF("som from report %u is %llu\n", ri->som.onmatch,
som);
}
PROGRAM_NEXT_INSTRUCTION
@@ -1016,11 +1029,13 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
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);
updateSeqPoint(tctxt, end, from_mpv);
const char do_som = t->hasSom; // TODO: constant propagate
const char is_external_report = 1;
enum DedupeResult rv =
dedupeCatchup(t, scratch, end, som, end + ri->offset_adjust,
ri->dkey, ri->offset_adjust,
is_external_report, ri->quash_som, do_som);
switch (rv) {
case DEDUPE_HALT:
return HWLM_TERMINATE_MATCHING;
@@ -1035,10 +1050,13 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
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);
updateSeqPoint(tctxt, end, from_mpv);
const char is_external_report = 0;
const char do_som = 1;
enum DedupeResult rv =
dedupeCatchup(t, scratch, end, som, end + ri->offset_adjust,
ri->dkey, ri->offset_adjust,
is_external_report, ri->quash_som, do_som);
switch (rv) {
case DEDUPE_HALT:
return HWLM_TERMINATE_MATCHING;
@@ -1053,9 +1071,10 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_CHAIN) {
if (roseCatchUpAndHandleChainMatch(t, scratch, ri->report,
end) ==
HWLM_TERMINATE_MATCHING) {
// Note: sequence points updated inside this function.
if (roseCatchUpAndHandleChainMatch(
t, scratch, ri->event, ri->top_squash_distance, end,
in_catchup) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
work_done = 1;
@@ -1063,20 +1082,22 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM_INT) {
roseHandleSom(t, scratch, ri->report, end);
updateSeqPoint(tctxt, end, from_mpv);
roseHandleSom(t, scratch, &ri->som, end);
work_done = 1;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM_AWARE) {
roseHandleSomSom(t, ri->report, som, end, scratch);
updateSeqPoint(tctxt, end, from_mpv);
roseHandleSomSom(t, scratch, &ri->som, som, end);
work_done = 1;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT) {
if (roseReport(t, scratch, end, ri->report, ri->onmatch,
ri->offset_adjust,
updateSeqPoint(tctxt, end, from_mpv);
if (roseReport(t, scratch, end, ri->onmatch, ri->offset_adjust,
INVALID_EKEY) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
@@ -1085,8 +1106,8 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_EXHAUST) {
if (roseReport(t, scratch, end, ri->report, ri->onmatch,
ri->offset_adjust,
updateSeqPoint(tctxt, end, from_mpv);
if (roseReport(t, scratch, end, ri->onmatch, ri->offset_adjust,
ri->ekey) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
@@ -1095,9 +1116,10 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM) {
const char is_exhaustible = 0;
if (roseReportSom(t, scratch, ri->report, som, end,
is_exhaustible) == HWLM_TERMINATE_MATCHING) {
updateSeqPoint(tctxt, end, from_mpv);
if (roseReportSom(t, scratch, som, end, ri->onmatch,
ri->offset_adjust,
INVALID_EKEY) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
work_done = 1;
@@ -1105,9 +1127,10 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM_EXHAUST) {
const char is_exhaustible = 1;
if (roseReportSom(t, scratch, ri->report, som, end,
is_exhaustible) == HWLM_TERMINATE_MATCHING) {
updateSeqPoint(tctxt, end, from_mpv);
if (roseReportSom(t, scratch, som, end, ri->onmatch,
ri->offset_adjust,
ri->ekey) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}
work_done = 1;
@@ -1115,11 +1138,13 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(DEDUPE_AND_REPORT) {
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);
updateSeqPoint(tctxt, end, from_mpv);
const char do_som = t->hasSom; // TODO: constant propagate
const char is_external_report = 1;
enum DedupeResult rv =
dedupeCatchup(t, scratch, end, som, end + ri->offset_adjust,
ri->dkey, ri->offset_adjust,
is_external_report, ri->quash_som, do_som);
switch (rv) {
case DEDUPE_HALT:
return HWLM_TERMINATE_MATCHING;
@@ -1132,8 +1157,7 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t,
}
const u32 ekey = INVALID_EKEY;
if (roseReport(t, scratch, end, ri->report, ir->onmatch,
ir->offsetAdjust,
if (roseReport(t, scratch, end, ri->onmatch, ri->offset_adjust,
ekey) == HWLM_TERMINATE_MATCHING) {
return HWLM_TERMINATE_MATCHING;
}

View File

@@ -41,8 +41,7 @@ void roseInitState(const struct RoseEngine *t, char *state);
void roseBlockEodExec(const struct RoseEngine *t, u64a offset,
struct hs_scratch *scratch);
void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch,
RoseCallback callback, RoseCallbackSom som_callback);
void roseBlockExec_i(const struct RoseEngine *t, struct hs_scratch *scratch);
static really_inline
int roseBlockHasEodWork(const struct RoseEngine *t,
@@ -79,8 +78,7 @@ int roseBlockHasEodWork(const struct RoseEngine *t,
/* assumes core_info in scratch has been init to point to data */
static really_inline
void roseBlockExec(const struct RoseEngine *t, struct hs_scratch *scratch,
RoseCallback callback, RoseCallbackSom som_callback) {
void roseBlockExec(const struct RoseEngine *t, struct hs_scratch *scratch) {
assert(t);
assert(scratch);
assert(scratch->core_info.buf);
@@ -101,7 +99,7 @@ void roseBlockExec(const struct RoseEngine *t, struct hs_scratch *scratch,
assert(t->maxBiAnchoredWidth == ROSE_BOUND_INF
|| length <= t->maxBiAnchoredWidth);
roseBlockExec_i(t, scratch, callback, som_callback);
roseBlockExec_i(t, scratch);
if (!t->requiresEodCheck) {
return;
@@ -121,16 +119,17 @@ void roseBlockExec(const struct RoseEngine *t, struct hs_scratch *scratch,
}
/* assumes core_info in scratch has been init to point to data */
void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
RoseCallback callback, RoseCallbackSom som_callback);
void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch);
void roseEodExec(const struct RoseEngine *t, u64a offset,
struct hs_scratch *scratch, RoseCallback callback,
RoseCallbackSom som_callback);
struct hs_scratch *scratch);
hwlmcb_rv_t rosePureLiteralCallback(size_t start, size_t end, u32 id,
void *context);
int roseReportAdaptor(u64a offset, ReportID id, void *context);
int roseReportSomAdaptor(u64a som, u64a offset, ReportID id, void *context);
int roseRunBoundaryProgram(const struct RoseEngine *rose, u32 program,
u64a stream_offset, struct hs_scratch *scratch);

View File

@@ -68,7 +68,6 @@
#include "util/compile_error.h"
#include "util/container.h"
#include "util/graph_range.h"
#include "util/internal_report.h"
#include "util/multibit_build.h"
#include "util/order_check.h"
#include "util/queue_index_factory.h"
@@ -196,6 +195,7 @@ public:
case ROSE_INSTR_ANCHORED_DELAY: return &u.anchoredDelay;
case ROSE_INSTR_PUSH_DELAYED: return &u.pushDelayed;
case ROSE_INSTR_CATCH_UP: return &u.catchUp;
case ROSE_INSTR_CATCH_UP_MPV: return &u.catchUpMpv;
case ROSE_INSTR_SOM_ADJUST: return &u.somAdjust;
case ROSE_INSTR_SOM_LEFTFIX: return &u.somLeftfix;
case ROSE_INSTR_SOM_FROM_REPORT: return &u.somFromReport;
@@ -206,7 +206,7 @@ public:
case ROSE_INSTR_DEDUPE_SOM: return &u.dedupeSom;
case ROSE_INSTR_REPORT_CHAIN: return &u.reportChain;
case ROSE_INSTR_REPORT_SOM_INT: return &u.reportSomInt;
case ROSE_INSTR_REPORT_SOM_AWARE: return &u.reportSom;
case ROSE_INSTR_REPORT_SOM_AWARE: return &u.reportSomAware;
case ROSE_INSTR_REPORT: return &u.report;
case ROSE_INSTR_REPORT_EXHAUST: return &u.reportExhaust;
case ROSE_INSTR_REPORT_SOM: return &u.reportSom;
@@ -240,6 +240,7 @@ public:
case ROSE_INSTR_ANCHORED_DELAY: return sizeof(u.anchoredDelay);
case ROSE_INSTR_PUSH_DELAYED: return sizeof(u.pushDelayed);
case ROSE_INSTR_CATCH_UP: return sizeof(u.catchUp);
case ROSE_INSTR_CATCH_UP_MPV: return sizeof(u.catchUpMpv);
case ROSE_INSTR_SOM_ADJUST: return sizeof(u.somAdjust);
case ROSE_INSTR_SOM_LEFTFIX: return sizeof(u.somLeftfix);
case ROSE_INSTR_SOM_FROM_REPORT: return sizeof(u.somFromReport);
@@ -250,7 +251,7 @@ public:
case ROSE_INSTR_DEDUPE_SOM: return sizeof(u.dedupeSom);
case ROSE_INSTR_REPORT_CHAIN: return sizeof(u.reportChain);
case ROSE_INSTR_REPORT_SOM_INT: return sizeof(u.reportSomInt);
case ROSE_INSTR_REPORT_SOM_AWARE: return sizeof(u.reportSom);
case ROSE_INSTR_REPORT_SOM_AWARE: return sizeof(u.reportSomAware);
case ROSE_INSTR_REPORT: return sizeof(u.report);
case ROSE_INSTR_REPORT_EXHAUST: return sizeof(u.reportExhaust);
case ROSE_INSTR_REPORT_SOM: return sizeof(u.reportSom);
@@ -283,6 +284,7 @@ public:
ROSE_STRUCT_ANCHORED_DELAY anchoredDelay;
ROSE_STRUCT_PUSH_DELAYED pushDelayed;
ROSE_STRUCT_CATCH_UP catchUp;
ROSE_STRUCT_CATCH_UP_MPV catchUpMpv;
ROSE_STRUCT_SOM_ADJUST somAdjust;
ROSE_STRUCT_SOM_LEFTFIX somLeftfix;
ROSE_STRUCT_SOM_FROM_REPORT somFromReport;
@@ -396,6 +398,9 @@ struct build_context : boost::noncopyable {
* matches, suffixes, outfixes etc. */
bool needs_catchup = false;
/** \brief True if this Rose engine has an MPV engine. */
bool needs_mpv_catchup = false;
/** \brief Resources in use (tracked as programs are added). */
RoseResources resources;
@@ -578,7 +583,7 @@ bool isPureFloating(const RoseResources &resources) {
}
static
bool isSingleOutfix(const RoseBuildImpl &tbi, u32 outfixEndQueue) {
bool isSingleOutfix(const RoseBuildImpl &tbi) {
for (auto v : vertices_range(tbi.g)) {
if (tbi.isAnyStart(v)) {
continue;
@@ -598,12 +603,12 @@ bool isSingleOutfix(const RoseBuildImpl &tbi, u32 outfixEndQueue) {
return false; /* streaming runtime makes liberal use of broken flag */
}
return outfixEndQueue == 1;
return tbi.outfixes.size() == 1;
}
static
u8 pickRuntimeImpl(const RoseBuildImpl &build, const build_context &bc,
u32 outfixEndQueue) {
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);
@@ -618,13 +623,38 @@ u8 pickRuntimeImpl(const RoseBuildImpl &build, const build_context &bc,
return ROSE_RUNTIME_PURE_LITERAL;
}
if (isSingleOutfix(build, outfixEndQueue)) {
if (isSingleOutfix(build)) {
return ROSE_RUNTIME_SINGLE_OUTFIX;
}
return ROSE_RUNTIME_FULL_ROSE;
}
/**
* \brief True if this Rose engine needs to run MPV catch up in front of
* non-MPV reports.
*/
static
bool needsMpvCatchup(const RoseBuildImpl &build) {
const auto &outfixes = build.outfixes;
bool has_mpv =
any_of(begin(outfixes), end(outfixes), [](const OutfixInfo &outfix) {
return outfix.is_nonempty_mpv();
});
if (!has_mpv) {
DEBUG_PRINTF("no mpv\n");
return false;
}
if (isSingleOutfix(build)) {
DEBUG_PRINTF("single outfix\n");
return false;
}
return true;
}
static
void fillStateOffsets(const RoseBuildImpl &tbi, u32 rolesWithStateCount,
u32 anchorStateSize, u32 activeArrayCount,
@@ -1941,32 +1971,6 @@ struct DerivedBoundaryReports {
set<ReportID> report_at_0_eod_full;
};
static
void fillInReportInfo(RoseEngine *engine, u32 reportOffset,
const ReportManager &rm, const vector<Report> &reports) {
internal_report *dest = (internal_report *)((char *)engine + reportOffset);
engine->intReportOffset = reportOffset;
engine->intReportCount = (u32)reports.size();
assert(ISALIGNED(dest));
for (const auto &report : reports) {
writeInternalReport(report, rm, dest++);
}
DEBUG_PRINTF("%zu reports of size %zu\n", reports.size(),
sizeof(internal_report));
}
static
bool hasSimpleReports(const vector<Report> &reports) {
auto it = find_if(reports.begin(), reports.end(), isComplexReport);
DEBUG_PRINTF("runtime has %scomplex reports\n",
it == reports.end() ? "no " : "");
return it == reports.end();
}
static
void prepSomRevNfas(const SomSlotManager &ssm, u32 *rev_nfa_table_offset,
vector<u32> *nfa_offsets, u32 *currOffset) {
@@ -2473,16 +2477,22 @@ void makeRoleAnchoredDelay(RoseBuildImpl &build, build_context &bc,
}
static
void makeDedupe(const ReportID id, vector<RoseInstruction> &report_block) {
void makeDedupe(const RoseBuildImpl &build, const Report &report,
vector<RoseInstruction> &report_block) {
auto ri = RoseInstruction(ROSE_INSTR_DEDUPE, JumpTarget::NEXT_BLOCK);
ri.u.dedupe.report = id;
ri.u.dedupe.quash_som = report.quashSom;
ri.u.dedupe.dkey = build.rm.getDkey(report);
ri.u.dedupe.offset_adjust = report.offsetAdjust;
report_block.push_back(move(ri));
}
static
void makeDedupeSom(const ReportID id, vector<RoseInstruction> &report_block) {
void makeDedupeSom(const RoseBuildImpl &build, const Report &report,
vector<RoseInstruction> &report_block) {
auto ri = RoseInstruction(ROSE_INSTR_DEDUPE_SOM, JumpTarget::NEXT_BLOCK);
ri.u.dedupeSom.report = id;
ri.u.dedupeSom.quash_som = report.quashSom;
ri.u.dedupeSom.dkey = build.rm.getDkey(report);
ri.u.dedupeSom.offset_adjust = report.offsetAdjust;
report_block.push_back(move(ri));
}
@@ -2510,6 +2520,92 @@ void makeCatchup(RoseBuildImpl &build, build_context &bc,
program.emplace_back(ROSE_INSTR_CATCH_UP);
}
static
void makeCatchupMpv(RoseBuildImpl &build, build_context &bc, ReportID id,
vector<RoseInstruction> &program) {
if (!bc.needs_mpv_catchup) {
return;
}
const Report &report = build.rm.getReport(id);
if (report.type == INTERNAL_ROSE_CHAIN) {
return;
}
program.emplace_back(ROSE_INSTR_CATCH_UP_MPV);
}
static
void writeSomOperation(const Report &report, som_operation *op) {
assert(op);
switch (report.type) {
case EXTERNAL_CALLBACK_SOM_REL:
op->type = SOM_EXTERNAL_CALLBACK_REL;
break;
case INTERNAL_SOM_LOC_SET:
op->type = SOM_INTERNAL_LOC_SET;
break;
case INTERNAL_SOM_LOC_SET_IF_UNSET:
op->type = SOM_INTERNAL_LOC_SET_IF_UNSET;
break;
case INTERNAL_SOM_LOC_SET_IF_WRITABLE:
op->type = SOM_INTERNAL_LOC_SET_IF_WRITABLE;
break;
case INTERNAL_SOM_LOC_SET_SOM_REV_NFA:
op->type = SOM_INTERNAL_LOC_SET_REV_NFA;
break;
case INTERNAL_SOM_LOC_SET_SOM_REV_NFA_IF_UNSET:
op->type = SOM_INTERNAL_LOC_SET_REV_NFA_IF_UNSET;
break;
case INTERNAL_SOM_LOC_SET_SOM_REV_NFA_IF_WRITABLE:
op->type = SOM_INTERNAL_LOC_SET_REV_NFA_IF_WRITABLE;
break;
case INTERNAL_SOM_LOC_COPY:
op->type = SOM_INTERNAL_LOC_COPY;
break;
case INTERNAL_SOM_LOC_COPY_IF_WRITABLE:
op->type = SOM_INTERNAL_LOC_COPY_IF_WRITABLE;
break;
case INTERNAL_SOM_LOC_MAKE_WRITABLE:
op->type = SOM_INTERNAL_LOC_MAKE_WRITABLE;
break;
case EXTERNAL_CALLBACK_SOM_STORED:
op->type = SOM_EXTERNAL_CALLBACK_STORED;
break;
case EXTERNAL_CALLBACK_SOM_ABS:
op->type = SOM_EXTERNAL_CALLBACK_ABS;
break;
case EXTERNAL_CALLBACK_SOM_REV_NFA:
op->type = SOM_EXTERNAL_CALLBACK_REV_NFA;
break;
case INTERNAL_SOM_LOC_SET_FROM:
op->type = SOM_INTERNAL_LOC_SET_FROM;
break;
case INTERNAL_SOM_LOC_SET_FROM_IF_WRITABLE:
op->type = SOM_INTERNAL_LOC_SET_FROM_IF_WRITABLE;
break;
default:
// This report doesn't correspond to a SOM operation.
assert(0);
throw CompileError("Unable to generate bytecode.");
}
op->onmatch = report.onmatch;
switch (report.type) {
case EXTERNAL_CALLBACK_SOM_REV_NFA:
case INTERNAL_SOM_LOC_SET_SOM_REV_NFA:
case INTERNAL_SOM_LOC_SET_SOM_REV_NFA_IF_UNSET:
case INTERNAL_SOM_LOC_SET_SOM_REV_NFA_IF_WRITABLE:
op->aux.revNfaIndex = report.revNfaIndex;
break;
default:
op->aux.somDistance = report.somDistance;
break;
}
}
static
void makeReport(RoseBuildImpl &build, const ReportID id,
const bool has_som, vector<RoseInstruction> &program) {
@@ -2536,10 +2632,12 @@ void makeReport(RoseBuildImpl &build, const ReportID id,
report_block.push_back(move(ri));
}
// External SOM reports need their SOM value calculated.
if (isExternalSomReport(report)) {
// External SOM reports that aren't passthrough need their SOM value
// calculated.
if (isExternalSomReport(report) &&
report.type != EXTERNAL_CALLBACK_SOM_PASS) {
auto ri = RoseInstruction(ROSE_INSTR_SOM_FROM_REPORT);
ri.u.somFromReport.report = id;
writeSomOperation(report, &ri.u.somFromReport.som);
report_block.push_back(move(ri));
}
@@ -2567,33 +2665,40 @@ void makeReport(RoseBuildImpl &build, const ReportID id,
if (needs_dedupe) {
report_block.emplace_back(ROSE_INSTR_DEDUPE_AND_REPORT,
JumpTarget::NEXT_BLOCK);
report_block.back().u.dedupeAndReport.report = id;
auto &ri = report_block.back();
ri.u.dedupeAndReport.quash_som = report.quashSom;
ri.u.dedupeAndReport.dkey = build.rm.getDkey(report);
ri.u.dedupeAndReport.onmatch = report.onmatch;
ri.u.dedupeAndReport.offset_adjust = report.offsetAdjust;
} else {
report_block.emplace_back(ROSE_INSTR_REPORT);
auto &ri = report_block.back();
ri.u.report.report = id;
ri.u.report.onmatch = report.onmatch;
ri.u.report.offset_adjust = report.offsetAdjust;
}
} else {
if (needs_dedupe) {
makeDedupe(id, report_block);
makeDedupe(build, report, report_block);
}
report_block.emplace_back(ROSE_INSTR_REPORT_EXHAUST);
auto &ri = report_block.back();
ri.u.reportExhaust.report = id;
ri.u.reportExhaust.onmatch = report.onmatch;
ri.u.reportExhaust.offset_adjust = report.offsetAdjust;
ri.u.reportExhaust.ekey = report.ekey;
}
} else { // has_som
makeDedupeSom(id, report_block);
makeDedupeSom(build, report, report_block);
if (report.ekey == INVALID_EKEY) {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM);
report_block.back().u.reportSom.report = id;
auto &ri = report_block.back();
ri.u.reportSom.onmatch = report.onmatch;
ri.u.reportSom.offset_adjust = report.offsetAdjust;
} else {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM_EXHAUST);
report_block.back().u.reportSomExhaust.report = id;
auto &ri = report_block.back();
ri.u.reportSomExhaust.onmatch = report.onmatch;
ri.u.reportSomExhaust.offset_adjust = report.offsetAdjust;
ri.u.reportSomExhaust.ekey = report.ekey;
}
}
break;
@@ -2610,29 +2715,55 @@ void makeReport(RoseBuildImpl &build, const ReportID id,
case INTERNAL_SOM_LOC_SET_FROM_IF_WRITABLE:
if (has_som) {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM_AWARE);
report_block.back().u.reportSomAware.report = id;
auto &ri = report_block.back();
writeSomOperation(report, &ri.u.reportSomAware.som);
} else {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM_INT);
report_block.back().u.reportSomInt.report = id;
auto &ri = report_block.back();
writeSomOperation(report, &ri.u.reportSomInt.som);
}
break;
case INTERNAL_ROSE_CHAIN:
case INTERNAL_ROSE_CHAIN: {
report_block.emplace_back(ROSE_INSTR_REPORT_CHAIN);
report_block.back().u.reportChain.report = id;
auto &ri = report_block.back();
ri.u.reportChain.event = report.onmatch;
ri.u.reportChain.top_squash_distance = report.topSquashDistance;
break;
}
case EXTERNAL_CALLBACK_SOM_REL:
case EXTERNAL_CALLBACK_SOM_STORED:
case EXTERNAL_CALLBACK_SOM_ABS:
case EXTERNAL_CALLBACK_SOM_REV_NFA:
makeDedupeSom(id, report_block);
makeDedupeSom(build, report, report_block);
if (report.ekey == INVALID_EKEY) {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM);
report_block.back().u.reportSom.report = id;
auto &ri = report_block.back();
ri.u.reportSom.onmatch = report.onmatch;
ri.u.reportSom.offset_adjust = report.offsetAdjust;
} else {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM_EXHAUST);
report_block.back().u.reportSomExhaust.report = id;
auto &ri = report_block.back();
ri.u.reportSomExhaust.onmatch = report.onmatch;
ri.u.reportSomExhaust.offset_adjust = report.offsetAdjust;
ri.u.reportSomExhaust.ekey = report.ekey;
}
break;
case EXTERNAL_CALLBACK_SOM_PASS:
makeDedupeSom(build, report, report_block);
if (report.ekey == INVALID_EKEY) {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM);
auto &ri = report_block.back();
ri.u.reportSom.onmatch = report.onmatch;
ri.u.reportSom.offset_adjust = report.offsetAdjust;
} else {
report_block.emplace_back(ROSE_INSTR_REPORT_SOM_EXHAUST);
auto &ri = report_block.back();
ri.u.reportSomExhaust.onmatch = report.onmatch;
ri.u.reportSomExhaust.offset_adjust = report.offsetAdjust;
ri.u.reportSomExhaust.ekey = report.ekey;
}
break;
default:
assert(0);
throw CompileError("Unable to generate bytecode.");
@@ -3571,6 +3702,26 @@ pair<u32, u32> buildLiteralPrograms(RoseBuildImpl &build, build_context &bc) {
return {litProgramsOffset, delayRebuildProgramsOffset};
}
static
u32 buildReportPrograms(RoseBuildImpl &build, build_context &bc) {
const auto &rm = build.rm;
const u32 numReports = verify_u32(rm.numReports());
vector<u32> programs(numReports);
vector<RoseInstruction> program;
for (ReportID id = 0; id < numReports; id++) {
program.clear();
const bool has_som = false;
makeCatchupMpv(build, bc, id, program);
makeReport(build, id, has_som, program);
programs[id] = writeProgram(bc, flattenProgram({program}));
DEBUG_PRINTF("program for report %u @ %u (%zu instructions)\n", id,
programs.back(), program.size());
}
return add_to_engine_blob(bc, begin(programs), end(programs));
}
static
vector<RoseInstruction> makeEodAnchorProgram(RoseBuildImpl &build,
build_context &bc,
@@ -3787,6 +3938,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
if (!anchored_dfas.empty()) {
bc.resources.has_anchored = true;
}
bc.needs_mpv_catchup = needsMpvCatchup(*this);
auto boundary_out = makeBoundaryPrograms(*this, bc, boundary, dboundary);
@@ -3835,6 +3987,8 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
u32 eodIterOffset;
tie(eodIterProgramOffset, eodIterOffset) = buildEodAnchorProgram(*this, bc);
u32 reportProgramOffset = buildReportPrograms(*this, bc);
vector<mmbit_sparse_iter> activeLeftIter;
buildActiveLeftIter(leftInfoTable, activeLeftIter);
@@ -3900,12 +4054,6 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
currOffset += verify_u32(sbsize);
}
const vector<Report> &int_reports = rm.reports();
currOffset = ROUNDUP_CL(currOffset);
u32 intReportOffset = currOffset;
currOffset += sizeof(internal_report) * int_reports.size();
u32 leftOffset = ROUNDUP_N(currOffset, alignof(LeftNfaInfo));
u32 roseLen = sizeof(LeftNfaInfo) * leftInfoTable.size();
currOffset = leftOffset + roseLen;
@@ -4004,14 +4152,13 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
engine->somHorizon = ssm.somPrecision();
engine->somLocationCount = ssm.numSomSlots();
engine->simpleCallback = !rm.numEkeys() && hasSimpleReports(rm.reports());
engine->needsCatchup = bc.needs_catchup ? 1 : 0;
fillInReportInfo(engine.get(), intReportOffset, rm, int_reports);
engine->literalCount = verify_u32(final_id_to_literal.size());
engine->litProgramOffset = litProgramOffset;
engine->litDelayRebuildProgramOffset = litDelayRebuildProgramOffset;
engine->reportProgramOffset = reportProgramOffset;
engine->reportProgramCount = verify_u32(rm.reports().size());
engine->runtimeImpl = pickRuntimeImpl(*this, bc, outfixEndQueue);
engine->mpvTriggeredByLeaf = anyEndfixMpvTriggers(*this);

View File

@@ -2833,7 +2833,7 @@ void mergePuffixes(RoseBuildImpl &tbi) {
u32 squashDistance =
allowedSquashDistance(repeat.reach, repeat.bounds.min, tbi, v);
Report ir = makeRoseTrigger(event, squashDistance);
Report ir = makeMpvTrigger(event, squashDistance);
ReportID id = tbi.rm.getInternalId(ir);
DEBUG_PRINTF("puffette event q%u t%u\n", queue, event);

View File

@@ -41,7 +41,6 @@
#include "nfa/nfa_dump_api.h"
#include "nfa/nfa_internal.h"
#include "util/dump_charclass.h"
#include "util/internal_report.h"
#include "util/multibit_internal.h"
#include "util/multibit.h"
@@ -192,20 +191,20 @@ void dumpJumpTable(ofstream &os, const RoseEngine *t,
}
static
void dumpReport(ofstream &os, const RoseEngine *t, ReportID report) {
const auto *ir =
(const internal_report *)loadFromByteCodeOffset(t, t->intReportOffset) +
report;
os << " type=" << u32{ir->type};
os << ", onmatch=" << ir->onmatch;
if (ir->ekey != INVALID_EKEY) {
os << ", ekey=" << ir->ekey;
void dumpSomOperation(ofstream &os, const som_operation &op) {
os << " som (type=" << u32{op.type} << ", onmatch=" << op.onmatch;
switch (op.type) {
case SOM_EXTERNAL_CALLBACK_REV_NFA:
case SOM_INTERNAL_LOC_SET_REV_NFA:
case SOM_INTERNAL_LOC_SET_REV_NFA_IF_UNSET:
case SOM_INTERNAL_LOC_SET_REV_NFA_IF_WRITABLE:
os << ", revNfaIndex=" << op.aux.revNfaIndex;
break;
default:
os << ", somDistance=" << op.aux.somDistance;
break;
}
if (ir->dkey != MO_INVALID_IDX) {
os << ", dkey=" << ir->dkey;
}
os << endl;
os << ")" << endl;
}
static
@@ -314,6 +313,9 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
PROGRAM_CASE(CATCH_UP) {}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(CATCH_UP_MPV) {}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(SOM_ADJUST) {
os << " distance " << ri->distance << endl;
}
@@ -326,8 +328,7 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(SOM_FROM_REPORT) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
dumpSomOperation(os, ri->som);
}
PROGRAM_NEXT_INSTRUCTION
@@ -348,64 +349,69 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(DEDUPE) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " quash_som " << u32{ri->quash_som} << endl;
os << " dkey " << ri->dkey << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
os << " fail_jump " << offset + ri->fail_jump << endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(DEDUPE_SOM) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " quash_som " << u32{ri->quash_som} << endl;
os << " dkey " << ri->dkey << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
os << " fail_jump " << offset + ri->fail_jump << endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_CHAIN) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " event " << ri->event << endl;
os << " top_squash_distance " << ri->top_squash_distance
<< endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM_INT) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
dumpSomOperation(os, ri->som);
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM_AWARE) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
dumpSomOperation(os, ri->som);
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " onmatch " << ri->onmatch << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_EXHAUST) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " onmatch " << ri->onmatch << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
os << " ekey " << ri->ekey << endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " onmatch " << ri->onmatch << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(REPORT_SOM_EXHAUST) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " onmatch " << ri->onmatch << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
os << " ekey " << ri->ekey << endl;
}
PROGRAM_NEXT_INSTRUCTION
PROGRAM_CASE(DEDUPE_AND_REPORT) {
os << " report " << ri->report << endl;
dumpReport(os, t, ri->report);
os << " quash_som " << u32{ri->quash_som} << endl;
os << " dkey " << ri->dkey << endl;
os << " onmatch " << ri->onmatch << endl;
os << " offset_adjust " << ri->offset_adjust << endl;
os << " fail_jump " << offset + ri->fail_jump << endl;
}
PROGRAM_NEXT_INSTRUCTION
@@ -537,6 +543,30 @@ void dumpRoseEodPrograms(const RoseEngine *t, const string &filename) {
os.close();
}
static
void dumpRoseReportPrograms(const RoseEngine *t, const string &filename) {
ofstream os(filename);
const u32 *programs =
(const u32 *)loadFromByteCodeOffset(t, t->reportProgramOffset);
for (u32 i = 0; i < t->reportProgramCount; i++) {
os << "Report " << i << endl;
os << "---------------" << endl;
if (programs[i]) {
os << "Program @ " << programs[i] << ":" << endl;
const char *prog =
(const char *)loadFromByteCodeOffset(t, programs[i]);
dumpProgram(os, t, prog);
} else {
os << "<No Program>" << endl;
}
}
os.close();
}
static
void dumpNfaNotes(ofstream &fout, const RoseEngine *t, const NFA *n) {
const u32 qindex = n->queueIndex;
@@ -834,9 +864,6 @@ void roseDumpText(const RoseEngine *t, FILE *f) {
if (t->hasSom) {
fprintf(f, " hasSom");
}
if (t->simpleCallback) {
fprintf(f, " simpleCallback");
}
fprintf(f, "\n");
fprintf(f, "dkey count : %u\n", t->dkeyCount);
@@ -949,7 +976,6 @@ void roseDumpStructRaw(const RoseEngine *t, FILE *f) {
DUMP_U8(t, canExhaust);
DUMP_U8(t, hasSom);
DUMP_U8(t, somHorizon);
DUMP_U8(t, simpleCallback);
DUMP_U8(t, needsCatchup);
DUMP_U32(t, mode);
DUMP_U32(t, historyRequired);
@@ -972,10 +998,10 @@ void roseDumpStructRaw(const RoseEngine *t, FILE *f) {
DUMP_U32(t, eodmatcherMinWidth);
DUMP_U32(t, amatcherMaxBiAnchoredWidth);
DUMP_U32(t, fmatcherMaxBiAnchoredWidth);
DUMP_U32(t, intReportOffset);
DUMP_U32(t, intReportCount);
DUMP_U32(t, litProgramOffset);
DUMP_U32(t, litDelayRebuildProgramOffset);
DUMP_U32(t, reportProgramOffset);
DUMP_U32(t, reportProgramCount);
DUMP_U32(t, literalCount);
DUMP_U32(t, activeArrayCount);
DUMP_U32(t, activeLeftCount);
@@ -1051,6 +1077,7 @@ void roseDumpComponents(const RoseEngine *t, bool dump_raw,
dumpRevNfas(t, dump_raw, base);
dumpRoseLitPrograms(t, base + "/rose_lit_programs.txt");
dumpRoseEodPrograms(t, base + "/rose_eod_programs.txt");
dumpRoseReportPrograms(t, base + "/rose_report_programs.txt");
}
void roseDumpInternals(const RoseEngine *t, const string &base) {

View File

@@ -305,8 +305,6 @@ struct RoseEngine {
u8 hasSom; /**< has at least one pattern which tracks SOM. */
u8 somHorizon; /**< width in bytes of SOM offset storage (governed by
SOM precision) */
u8 simpleCallback; /**< has only external reports with no bounds checks,
plus no exhaustion keys */
u8 needsCatchup; /** catch up needs to be run on every report. */
u32 mode; /**< scanning mode, one of HS_MODE_{BLOCK,STREAM,VECTORED} */
u32 historyRequired; /**< max amount of history required for streaming */
@@ -343,9 +341,6 @@ struct RoseEngine {
u32 fmatcherMaxBiAnchoredWidth; /**< maximum number of bytes that can still
* produce a match for a pattern involved
* with the anchored table. */
u32 intReportOffset; /**< offset of array of internal_report structures */
u32 intReportCount; /**< number of internal_report structures */
/** \brief Offset of u32 array of program offsets for literals. */
u32 litProgramOffset;
@@ -353,6 +348,12 @@ struct RoseEngine {
* literals. */
u32 litDelayRebuildProgramOffset;
/** \brief Offset of u32 array of program offsets for internal reports. */
u32 reportProgramOffset;
/** \brief Number of programs for internal reports. */
u32 reportProgramCount;
/**
* \brief Number of entries in the arrays pointed to by litProgramOffset,
* litDelayRebuildProgramOffset.

View File

@@ -33,6 +33,7 @@
#ifndef ROSE_ROSE_PROGRAM_H
#define ROSE_ROSE_PROGRAM_H
#include "som/som_operation.h"
#include "rose_internal.h"
#include "ue2common.h"
@@ -53,9 +54,10 @@ enum RoseInstructionCode {
ROSE_INSTR_CHECK_PREFIX, //!< Prefix engine must be in accept state.
ROSE_INSTR_PUSH_DELAYED, //!< Push delayed literal matches.
ROSE_INSTR_CATCH_UP, //!< Catch up engines, anchored matches.
ROSE_INSTR_CATCH_UP_MPV, //!< Catch up the MPV.
ROSE_INSTR_SOM_ADJUST, //!< Set SOM from a distance to EOM.
ROSE_INSTR_SOM_LEFTFIX, //!< Acquire SOM from a leftfix engine.
ROSE_INSTR_SOM_FROM_REPORT, //!< Acquire SOM from an internal_report.
ROSE_INSTR_SOM_FROM_REPORT, //!< Acquire SOM from a som_operation.
ROSE_INSTR_SOM_ZERO, //!< Set SOM to zero.
ROSE_INSTR_TRIGGER_INFIX, //!< Trigger an infix engine.
ROSE_INSTR_TRIGGER_SUFFIX, //!< Trigger a suffix engine.
@@ -171,6 +173,10 @@ struct ROSE_STRUCT_CATCH_UP {
u8 code; //!< From enum RoseInstructionCode.
};
struct ROSE_STRUCT_CATCH_UP_MPV {
u8 code; //!< From enum RoseInstructionCode.
};
struct ROSE_STRUCT_SOM_ADJUST {
u8 code; //!< From enum RoseInstructionCode.
u32 distance; //!< Distance to EOM.
@@ -184,7 +190,7 @@ struct ROSE_STRUCT_SOM_LEFTFIX {
struct ROSE_STRUCT_SOM_FROM_REPORT {
u8 code; //!< From enum RoseInstructionCode.
ReportID report; //!< EXTERNAL_CALLBACK_SOM_* report to use.
struct som_operation som;
};
struct ROSE_STRUCT_SOM_ZERO {
@@ -206,41 +212,49 @@ struct ROSE_STRUCT_TRIGGER_SUFFIX {
struct ROSE_STRUCT_DEDUPE {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
u8 quash_som; //!< Force SOM to zero for this report.
u32 dkey; //!< Dedupe key.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
u32 fail_jump; //!< Jump forward this many bytes on failure.
};
struct ROSE_STRUCT_DEDUPE_SOM {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
u8 quash_som; //!< Force SOM to zero for this report.
u32 dkey; //!< Dedupe key.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
u32 fail_jump; //!< Jump forward this many bytes on failure.
};
struct ROSE_STRUCT_REPORT_CHAIN {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
u32 event; //!< Queue event, from MQE_*. Must be a top.
/**
* \brief Number of bytes behind us that we are allowed to squash
* identical top events on the queue.
*/
u64a top_squash_distance;
};
struct ROSE_STRUCT_REPORT_SOM_INT {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
struct som_operation som;
};
struct ROSE_STRUCT_REPORT_SOM_AWARE {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
struct som_operation som;
};
struct ROSE_STRUCT_REPORT {
u8 code; //!< From enum RoseInstructionCode.
ReportID report; //!< Internal report ID (used for assertions).
ReportID onmatch; //!< Report ID to deliver to user.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
};
struct ROSE_STRUCT_REPORT_EXHAUST {
u8 code; //!< From enum RoseInstructionCode.
ReportID report; //!< Internal report ID (used for assertions).
ReportID onmatch; //!< Report ID to deliver to user.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
u32 ekey; //!< Exhaustion key.
@@ -248,22 +262,23 @@ struct ROSE_STRUCT_REPORT_EXHAUST {
struct ROSE_STRUCT_REPORT_SOM {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
ReportID onmatch; //!< Report ID to deliver to user.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
};
struct ROSE_STRUCT_REPORT_SOM_EXHAUST {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
};
struct ROSE_STRUCT_REPORT_SOM_EXT {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
ReportID onmatch; //!< Report ID to deliver to user.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
u32 ekey; //!< Exhaustion key.
};
struct ROSE_STRUCT_DEDUPE_AND_REPORT {
u8 code; //!< From enum RoseInstructionCode.
ReportID report;
u8 quash_som; //!< Force SOM to zero for this report.
u32 dkey; //!< Dedupe key.
ReportID onmatch; //!< Report ID to deliver to user.
s32 offset_adjust; //!< Offset adjustment to apply to end offset.
u32 fail_jump; //!< Jump forward this many bytes on failure.
};

View File

@@ -33,10 +33,9 @@
#ifndef ROSE_RUNTIME_H
#define ROSE_RUNTIME_H
#include "scratch.h"
#include "rose_internal.h"
#include "scratch.h"
#include "util/exhaust.h" // for isExhausted
#include "util/internal_report.h"
#include "util/partial_store.h"
/*
@@ -147,16 +146,6 @@ u32 has_chained_nfas(const struct RoseEngine *t) {
return t->outfixBeginQueue;
}
/** \brief Fetch \ref internal_report structure for this internal ID. */
static really_inline
const struct internal_report *getInternalReport(const struct RoseEngine *t,
ReportID intId) {
const struct internal_report *reports =
(const struct internal_report *)((const u8 *)t + t->intReportOffset);
assert(intId < t->intReportCount);
return reports + intId;
}
static really_inline
void updateLastMatchOffset(struct RoseContext *tctxt, u64a offset) {
DEBUG_PRINTF("match @%llu, last match @%llu\n", offset,

View File

@@ -422,8 +422,7 @@ void do_rebuild(const struct RoseEngine *t, const struct HWLM *ftable,
assert(!can_stop_matching(scratch));
}
void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
RoseCallback callback, RoseCallbackSom som_callback) {
void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch) {
DEBUG_PRINTF("OH HAI\n");
assert(t);
assert(scratch->core_info.hbuf);
@@ -457,8 +456,6 @@ void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch,
tctxt->delayLastEndOffset = offset;
tctxt->lastEndOffset = offset;
tctxt->filledDelayedSlots = 0;
tctxt->cb = callback;
tctxt->cb_som = som_callback;
tctxt->lastMatchOffset = 0;
tctxt->minMatchOffset = offset;
tctxt->minNonMpvMatchOffset = offset;