From 5a1dd54049021440b4544ee42aa33423804f60b2 Mon Sep 17 00:00:00 2001 From: Justin Viiret Date: Thu, 11 Feb 2016 15:21:18 +1100 Subject: [PATCH] Split CHECK_LEFTFIX into CHECK_{INFIX,PREFIX} --- src/rose/program_runtime.h | 57 +++++++++++++++++++++++--------- src/rose/rose_build_bytecode.cpp | 37 +++++++++++++++------ src/rose/rose_dump.cpp | 10 +++++- src/rose/rose_program.h | 13 ++++++-- 4 files changed, 89 insertions(+), 28 deletions(-) diff --git a/src/rose/program_runtime.h b/src/rose/program_runtime.h index bdada9e1..590d9ec3 100644 --- a/src/rose/program_runtime.h +++ b/src/rose/program_runtime.h @@ -144,8 +144,9 @@ void rosePushDelayedMatch(const struct RoseEngine *t, static rose_inline char roseLeftfixCheckMiracles(const struct RoseEngine *t, const struct LeftNfaInfo *left, - struct core_info *ci, struct mq *q, u64a end) { - if (left->transient) { + struct core_info *ci, struct mq *q, u64a end, + const char is_infix) { + if (!is_infix && left->transient) { // Miracles won't help us with transient leftfix engines; they only // scan for a limited time anyway. return 1; @@ -178,7 +179,7 @@ found_miracle: // If we're a prefix, then a miracle effectively results in us needing to // re-init our state and start fresh. - if (!left->infix) { + if (!is_infix) { if (miracle_loc != begin_loc) { DEBUG_PRINTF("re-init prefix state\n"); q->cur = q->end = 0; @@ -355,9 +356,10 @@ hwlmcb_rv_t roseTriggerSuffix(const struct RoseEngine *t, return HWLM_CONTINUE_MATCHING; } -static rose_inline +static really_inline char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, - u32 qi, u32 leftfixLag, ReportID leftfixReport, u64a end) { + u32 qi, u32 leftfixLag, ReportID leftfixReport, u64a end, + const char is_infix) { struct core_info *ci = &scratch->core_info; u32 ri = queueToLeftIndex(t, qi); @@ -365,10 +367,12 @@ char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, DEBUG_PRINTF("testing %s %s %u/%u with lag %u (maxLag=%u)\n", (left->transient ? "transient" : "active"), - (left->infix ? "infix" : "prefix"), + (is_infix ? "infix" : "prefix"), ri, qi, leftfixLag, left->maxLag); assert(leftfixLag <= left->maxLag); + assert(left->infix == is_infix); + assert(!is_infix || !left->transient); // Only prefixes can be transient. struct mq *q = scratch->queues + qi; char *state = scratch->core_info.state; @@ -398,7 +402,7 @@ char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, initRoseQueue(t, qi, left, scratch); if (ci->buf_offset) { // there have been writes before us! s32 sp; - if (left->transient) { + if (!is_infix && left->transient) { sp = -(s32)ci->hlen; } else { sp = -(s32)loadRoseDelay(t, state, left); @@ -408,7 +412,7 @@ char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, * at stream boundary */ pushQueueAt(q, 0, MQE_START, sp); - if (left->infix || (ci->buf_offset + sp > 0 && !left->transient)) { + if (is_infix || (ci->buf_offset + sp > 0 && !left->transient)) { loadStreamState(q->nfa, q, sp); } else { pushQueueAt(q, 1, MQE_TOP, sp); @@ -425,7 +429,7 @@ char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, assert(loc >= q_cur_loc(q)); assert(leftfixReport != MO_INVALID_IDX); - if (left->transient) { + if (!is_infix && left->transient) { s64a start_loc = loc - left->transient; if (q_cur_loc(q) < start_loc) { q->cur = q->end = 0; @@ -436,7 +440,7 @@ char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, } if (q_cur_loc(q) < loc || q_last_type(q) != MQE_START) { - if (left->infix) { + if (is_infix) { if (infixTooOld(q, loc)) { DEBUG_PRINTF("infix %u died of old age\n", ri); goto nfa_dead; @@ -445,7 +449,7 @@ char roseTestLeftfix(const struct RoseEngine *t, struct hs_scratch *scratch, reduceInfixQueue(q, loc, left->maxQueueLen, q->nfa->maxWidth); } - if (!roseLeftfixCheckMiracles(t, left, ci, q, end)) { + if (!roseLeftfixCheckMiracles(t, left, ci, q, end, is_infix)) { DEBUG_PRINTF("leftfix %u died due to miracle\n", ri); goto nfa_dead; } @@ -482,6 +486,18 @@ nfa_dead: return 0; } +static rose_inline +char roseTestPrefix(const struct RoseEngine *t, struct hs_scratch *scratch, + u32 qi, u32 leftfixLag, ReportID leftfixReport, u64a end) { + return roseTestLeftfix(t, scratch, qi, leftfixLag, leftfixReport, end, 0); +} + +static rose_inline +char roseTestInfix(const struct RoseEngine *t, struct hs_scratch *scratch, + u32 qi, u32 leftfixLag, ReportID leftfixReport, u64a end) { + return roseTestLeftfix(t, scratch, qi, leftfixLag, leftfixReport, end, 1); +} + static rose_inline void roseTriggerInfix(const struct RoseEngine *t, struct hs_scratch *scratch, u64a start, u64a end, u32 qi, u32 topEvent, u8 cancel) { @@ -921,10 +937,21 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, } PROGRAM_NEXT_INSTRUCTION - PROGRAM_CASE(CHECK_LEFTFIX) { - if (!roseTestLeftfix(t, scratch, ri->queue, ri->lag, ri->report, - end)) { - DEBUG_PRINTF("failed leftfix check\n"); + PROGRAM_CASE(CHECK_INFIX) { + if (!roseTestInfix(t, scratch, ri->queue, ri->lag, ri->report, + end)) { + DEBUG_PRINTF("failed infix check\n"); + assert(ri->fail_jump); // must progress + pc += ri->fail_jump; + continue; + } + } + PROGRAM_NEXT_INSTRUCTION + + PROGRAM_CASE(CHECK_PREFIX) { + if (!roseTestPrefix(t, scratch, ri->queue, ri->lag, ri->report, + end)) { + DEBUG_PRINTF("failed prefix check\n"); assert(ri->fail_jump); // must progress pc += ri->fail_jump; continue; diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 5354955a..4518b434 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -194,7 +194,8 @@ public: case ROSE_INSTR_CHECK_BOUNDS: return &u.checkBounds; case ROSE_INSTR_CHECK_NOT_HANDLED: return &u.checkNotHandled; case ROSE_INSTR_CHECK_LOOKAROUND: return &u.checkLookaround; - case ROSE_INSTR_CHECK_LEFTFIX: return &u.checkLeftfix; + case ROSE_INSTR_CHECK_INFIX: return &u.checkInfix; + case ROSE_INSTR_CHECK_PREFIX: return &u.checkPrefix; case ROSE_INSTR_ANCHORED_DELAY: return &u.anchoredDelay; case ROSE_INSTR_PUSH_DELAYED: return &u.pushDelayed; case ROSE_INSTR_CATCH_UP: return &u.catchUp; @@ -236,7 +237,8 @@ public: case ROSE_INSTR_CHECK_BOUNDS: return sizeof(u.checkBounds); case ROSE_INSTR_CHECK_NOT_HANDLED: return sizeof(u.checkNotHandled); case ROSE_INSTR_CHECK_LOOKAROUND: return sizeof(u.checkLookaround); - case ROSE_INSTR_CHECK_LEFTFIX: return sizeof(u.checkLeftfix); + case ROSE_INSTR_CHECK_INFIX: return sizeof(u.checkInfix); + case ROSE_INSTR_CHECK_PREFIX: return sizeof(u.checkPrefix); 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); @@ -277,7 +279,8 @@ public: ROSE_STRUCT_CHECK_BOUNDS checkBounds; ROSE_STRUCT_CHECK_NOT_HANDLED checkNotHandled; ROSE_STRUCT_CHECK_LOOKAROUND checkLookaround; - ROSE_STRUCT_CHECK_LEFTFIX checkLeftfix; + ROSE_STRUCT_CHECK_INFIX checkInfix; + ROSE_STRUCT_CHECK_PREFIX checkPrefix; ROSE_STRUCT_ANCHORED_DELAY anchoredDelay; ROSE_STRUCT_PUSH_DELAYED pushDelayed; ROSE_STRUCT_CATCH_UP catchUp; @@ -2724,8 +2727,11 @@ flattenProgram(const vector> &programs) { case ROSE_INSTR_CHECK_LOOKAROUND: ri.u.checkLookaround.fail_jump = jump_val; break; - case ROSE_INSTR_CHECK_LEFTFIX: - ri.u.checkLeftfix.fail_jump = jump_val; + case ROSE_INSTR_CHECK_INFIX: + ri.u.checkInfix.fail_jump = jump_val; + break; + case ROSE_INSTR_CHECK_PREFIX: + ri.u.checkPrefix.fail_jump = jump_val; break; case ROSE_INSTR_DEDUPE: ri.u.dedupe.fail_jump = jump_val; @@ -2986,11 +2992,22 @@ void makeRoleCheckLeftfix(RoseBuildImpl &build, build_context &bc, RoseVertex v, assert(!build.cc.streaming || build.g[v].left.lag <= MAX_STORED_LEFTFIX_LAG); - auto ri = RoseInstruction(ROSE_INSTR_CHECK_LEFTFIX, JumpTarget::NEXT_BLOCK); - ri.u.checkLeftfix.queue = lni.queue; - ri.u.checkLeftfix.lag = build.g[v].left.lag; - ri.u.checkLeftfix.report = build.g[v].left.leftfix_report; - program.push_back(ri); + bool is_prefix = build.isRootSuccessor(v); + if (is_prefix) { + auto ri = + RoseInstruction(ROSE_INSTR_CHECK_PREFIX, JumpTarget::NEXT_BLOCK); + ri.u.checkPrefix.queue = lni.queue; + ri.u.checkPrefix.lag = build.g[v].left.lag; + ri.u.checkPrefix.report = build.g[v].left.leftfix_report; + program.push_back(move(ri)); + } else { + auto ri = + RoseInstruction(ROSE_INSTR_CHECK_INFIX, JumpTarget::NEXT_BLOCK); + ri.u.checkInfix.queue = lni.queue; + ri.u.checkInfix.lag = build.g[v].left.lag; + ri.u.checkInfix.report = build.g[v].left.leftfix_report; + program.push_back(move(ri)); + } } static diff --git a/src/rose/rose_dump.cpp b/src/rose/rose_dump.cpp index 25c6e77d..a188c78b 100644 --- a/src/rose/rose_dump.cpp +++ b/src/rose/rose_dump.cpp @@ -288,7 +288,15 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) { } PROGRAM_NEXT_INSTRUCTION - PROGRAM_CASE(CHECK_LEFTFIX) { + PROGRAM_CASE(CHECK_INFIX) { + os << " queue " << ri->queue << endl; + os << " lag " << ri->lag << endl; + os << " report " << ri->report << endl; + os << " fail_jump +" << ri->fail_jump << endl; + } + PROGRAM_NEXT_INSTRUCTION + + PROGRAM_CASE(CHECK_PREFIX) { os << " queue " << ri->queue << endl; os << " lag " << ri->lag << endl; os << " report " << ri->report << endl; diff --git a/src/rose/rose_program.h b/src/rose/rose_program.h index 81852f09..36a9aabd 100644 --- a/src/rose/rose_program.h +++ b/src/rose/rose_program.h @@ -49,7 +49,8 @@ enum RoseInstructionCode { ROSE_INSTR_CHECK_BOUNDS, //!< Bounds on distance from offset 0. ROSE_INSTR_CHECK_NOT_HANDLED, //!< Test & set role in "handled". ROSE_INSTR_CHECK_LOOKAROUND, //!< Lookaround check. - ROSE_INSTR_CHECK_LEFTFIX, //!< Leftfix must be in accept state. + ROSE_INSTR_CHECK_INFIX, //!< Infix engine must be in accept state. + 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_SOM_ADJUST, //!< Set SOM from a distance to EOM. @@ -141,7 +142,15 @@ struct ROSE_STRUCT_CHECK_LOOKAROUND { u32 fail_jump; //!< Jump forward this many bytes on failure. }; -struct ROSE_STRUCT_CHECK_LEFTFIX { +struct ROSE_STRUCT_CHECK_INFIX { + u8 code; //!< From enum RoseInstructionCode. + u32 queue; //!< Queue of leftfix to check. + u32 lag; //!< Lag of leftfix for this case. + ReportID report; //!< ReportID of leftfix to check. + u32 fail_jump; //!< Jump forward this many bytes on failure. +}; + +struct ROSE_STRUCT_CHECK_PREFIX { u8 code; //!< From enum RoseInstructionCode. u32 queue; //!< Queue of leftfix to check. u32 lag; //!< Lag of leftfix for this case.