Split CHECK_LEFTFIX into CHECK_{INFIX,PREFIX}

This commit is contained in:
Justin Viiret 2016-02-11 15:21:18 +11:00 committed by Matthew Barr
parent 7a775e5fab
commit 5a1dd54049
4 changed files with 89 additions and 28 deletions

View File

@ -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;

View File

@ -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<vector<RoseInstruction>> &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

View File

@ -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;

View File

@ -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.