diff --git a/src/rose/program_runtime.h b/src/rose/program_runtime.h index 78397070..a913ae27 100644 --- a/src/rose/program_runtime.h +++ b/src/rose/program_runtime.h @@ -880,9 +880,9 @@ hwlmcb_rv_t roseRunProgram(const struct RoseEngine *t, PROGRAM_NEXT_INSTRUCTION PROGRAM_CASE(CHECK_LIT_EARLY) { - if (end < t->floatingMinLiteralMatchOffset) { - DEBUG_PRINTF("halt: too soon, min offset=%u\n", - t->floatingMinLiteralMatchOffset); + if (end < ri->min_offset) { + DEBUG_PRINTF("halt: before min_offset=%u\n", + ri->min_offset); return HWLM_CONTINUE_MATCHING; } } diff --git a/src/rose/rose_build_bytecode.cpp b/src/rose/rose_build_bytecode.cpp index 3d1b5c6b..b148155b 100644 --- a/src/rose/rose_build_bytecode.cpp +++ b/src/rose/rose_build_bytecode.cpp @@ -3568,6 +3568,19 @@ void makeGroupSquashInstruction(const RoseBuildImpl &build, u32 final_id, program.push_back(move(ri)); } +static +u32 findMinOffset(const RoseBuildImpl &build, u32 lit_id) { + const auto &lit_vertices = build.literal_info.at(lit_id).vertices; + assert(!lit_vertices.empty()); + + u32 min_offset = UINT32_MAX; + for (const auto &v : lit_vertices) { + min_offset = min(min_offset, build.g[v].min_offset); + } + + return min_offset; +} + static void makeCheckLitEarlyInstruction(const RoseBuildImpl &build, build_context &bc, u32 final_id, @@ -3591,22 +3604,36 @@ void makeCheckLitEarlyInstruction(const RoseBuildImpl &build, build_context &bc, return; } - size_t min_offset = SIZE_MAX; + size_t min_len = SIZE_MAX; + u32 min_offset = UINT32_MAX; for (u32 lit_id : lit_ids) { const auto &lit = build.literals.right.at(lit_id); - min_offset = min(min_offset, lit.elength()); + size_t lit_min_len = lit.elength(); + u32 lit_min_offset = findMinOffset(build, lit_id); + DEBUG_PRINTF("lit_id=%u has min_len=%zu, min_offset=%u\n", lit_id, + lit_min_len, lit_min_offset); + min_len = min(min_len, lit_min_len); + min_offset = min(min_offset, lit_min_offset); } - DEBUG_PRINTF("%zu lits, min_offset=%zu\n", lit_ids.size(), min_offset); + DEBUG_PRINTF("final_id=%u has min_len=%zu, min_offset=%u, " + "global min is %u\n", final_id, min_len, min_offset, + bc.floatingMinLiteralMatchOffset); // If we can't match before the min offset, we don't need the check. - if (min_offset >= bc.floatingMinLiteralMatchOffset) { + if (min_len >= bc.floatingMinLiteralMatchOffset) { DEBUG_PRINTF("no need for check, min is %u\n", - bc.floatingMinLiteralMatchOffset); + bc.floatingMinLiteralMatchOffset); return; } - program.push_back(RoseInstruction(ROSE_INSTR_CHECK_LIT_EARLY)); + assert(min_offset >= bc.floatingMinLiteralMatchOffset); + assert(min_offset < UINT32_MAX); + + DEBUG_PRINTF("adding lit early check, min_offset=%u\n", min_offset); + auto ri = RoseInstruction(ROSE_INSTR_CHECK_LIT_EARLY); + ri.u.checkLitEarly.min_offset = min_offset; + program.push_back(move(ri)); } static diff --git a/src/rose/rose_dump.cpp b/src/rose/rose_dump.cpp index f6badd1b..ad776780 100644 --- a/src/rose/rose_dump.cpp +++ b/src/rose/rose_dump.cpp @@ -253,7 +253,9 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) { } PROGRAM_NEXT_INSTRUCTION - PROGRAM_CASE(CHECK_LIT_EARLY) {} + PROGRAM_CASE(CHECK_LIT_EARLY) { + os << " min_offset " << ri->min_offset << endl; + } PROGRAM_NEXT_INSTRUCTION PROGRAM_CASE(CHECK_GROUPS) { diff --git a/src/rose/rose_program.h b/src/rose/rose_program.h index 01572dbd..5c57bf54 100644 --- a/src/rose/rose_program.h +++ b/src/rose/rose_program.h @@ -120,6 +120,7 @@ struct ROSE_STRUCT_CHECK_LIT_MASK { /** Note: check failure will halt program. */ struct ROSE_STRUCT_CHECK_LIT_EARLY { u8 code; //!< From enum RoseInstructionCode. + u32 min_offset; //!< Minimum offset for this literal. }; /** Note: check failure will halt program. */