mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
rose_program: merge RECORD_ANCHORED instruction into ANCHORED_DELAY
This commit is contained in:
parent
e24c38a85c
commit
f74f475189
@ -1892,6 +1892,8 @@ hwlmcb_rv_t roseRunProgram_i(const struct RoseEngine *t,
|
|||||||
DEBUG_PRINTF("delay until playback\n");
|
DEBUG_PRINTF("delay until playback\n");
|
||||||
tctxt->groups |= ri->groups;
|
tctxt->groups |= ri->groups;
|
||||||
work_done = 1;
|
work_done = 1;
|
||||||
|
recordAnchoredLiteralMatch(t, scratch, ri->anch_id, end);
|
||||||
|
|
||||||
assert(ri->done_jump); // must progress
|
assert(ri->done_jump); // must progress
|
||||||
pc += ri->done_jump;
|
pc += ri->done_jump;
|
||||||
continue;
|
continue;
|
||||||
@ -2085,8 +2087,8 @@ hwlmcb_rv_t roseRunProgram_i(const struct RoseEngine *t,
|
|||||||
}
|
}
|
||||||
PROGRAM_NEXT_INSTRUCTION
|
PROGRAM_NEXT_INSTRUCTION
|
||||||
|
|
||||||
PROGRAM_CASE(RECORD_ANCHORED) {
|
PROGRAM_CASE(DUMMY_NOP) {
|
||||||
recordAnchoredLiteralMatch(t, scratch, ri->id, end);
|
assert(0);
|
||||||
}
|
}
|
||||||
PROGRAM_NEXT_INSTRUCTION
|
PROGRAM_NEXT_INSTRUCTION
|
||||||
|
|
||||||
|
@ -3615,22 +3615,37 @@ void makeRoleCheckLeftfix(const RoseBuildImpl &build,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void makeRoleAnchoredDelay(const RoseBuildImpl &build,
|
void makeAnchoredLiteralDelay(const RoseBuildImpl &build,
|
||||||
u32 floatingMinLiteralMatchOffset,
|
const ProgramBuild &prog_build, u32 lit_id,
|
||||||
RoseVertex v, RoseProgram &program) {
|
RoseProgram &program) {
|
||||||
// Only relevant for roles that can be triggered by the anchored table.
|
// Only relevant for literals in the anchored table.
|
||||||
if (!build.isAnchored(v)) {
|
const rose_literal_id &lit = build.literals.right.at(lit_id);
|
||||||
|
if (lit.table != ROSE_ANCHORED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this match cannot occur after floatingMinLiteralMatchOffset, we do
|
// If this literal match cannot occur after floatingMinLiteralMatchOffset,
|
||||||
// not need this check.
|
// we do not need this check.
|
||||||
if (build.g[v].max_offset <= floatingMinLiteralMatchOffset) {
|
bool all_too_early = true;
|
||||||
|
rose_group groups = 0;
|
||||||
|
|
||||||
|
const auto &lit_vertices = build.literal_info.at(lit_id).vertices;
|
||||||
|
for (RoseVertex v : lit_vertices) {
|
||||||
|
if (build.g[v].max_offset > prog_build.floatingMinLiteralMatchOffset) {
|
||||||
|
all_too_early = false;
|
||||||
|
}
|
||||||
|
groups |= build.g[v].groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (all_too_early) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(contains(prog_build.anchored_programs, lit_id));
|
||||||
|
u32 anch_id = prog_build.anchored_programs.at(lit_id);
|
||||||
|
|
||||||
const auto *end_inst = program.end_instruction();
|
const auto *end_inst = program.end_instruction();
|
||||||
auto ri = make_unique<RoseInstrAnchoredDelay>(build.g[v].groups, end_inst);
|
auto ri = make_unique<RoseInstrAnchoredDelay>(groups, anch_id, end_inst);
|
||||||
program.add_before_end(move(ri));
|
program.add_before_end(move(ri));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4175,9 +4190,6 @@ RoseProgram makeRoleProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
// First, add program instructions that enforce preconditions without
|
// First, add program instructions that enforce preconditions without
|
||||||
// effects.
|
// effects.
|
||||||
|
|
||||||
makeRoleAnchoredDelay(build, prog_build.floatingMinLiteralMatchOffset, v,
|
|
||||||
program);
|
|
||||||
|
|
||||||
if (onlyAtEod(build, v)) {
|
if (onlyAtEod(build, v)) {
|
||||||
DEBUG_PRINTF("only at eod\n");
|
DEBUG_PRINTF("only at eod\n");
|
||||||
const auto *end_inst = program.end_instruction();
|
const auto *end_inst = program.end_instruction();
|
||||||
@ -4626,21 +4638,6 @@ u32 findMaxOffset(const RoseBuildImpl &build, u32 lit_id) {
|
|||||||
return max_offset;
|
return max_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
void makeRecordAnchoredInstruction(const RoseBuildImpl &build,
|
|
||||||
ProgramBuild &prog_build, u32 lit_id,
|
|
||||||
RoseProgram &program) {
|
|
||||||
if (build.literals.right.at(lit_id).table != ROSE_ANCHORED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!contains(prog_build.anchored_programs, lit_id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto anch_id = prog_build.anchored_programs.at(lit_id);
|
|
||||||
DEBUG_PRINTF("adding RECORD_ANCHORED for anch_id=%u\n", anch_id);
|
|
||||||
program.add_before_end(make_unique<RoseInstrRecordAnchored>(anch_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
u32 findMinOffset(const RoseBuildImpl &build, u32 lit_id) {
|
u32 findMinOffset(const RoseBuildImpl &build, u32 lit_id) {
|
||||||
const auto &lit_vertices = build.literal_info.at(lit_id).vertices;
|
const auto &lit_vertices = build.literal_info.at(lit_id).vertices;
|
||||||
@ -4768,8 +4765,8 @@ bool hasDelayedLiteral(const RoseBuildImpl &build,
|
|||||||
static
|
static
|
||||||
RoseProgram makeLitInitialProgram(const RoseBuildImpl &build,
|
RoseProgram makeLitInitialProgram(const RoseBuildImpl &build,
|
||||||
build_context &bc, ProgramBuild &prog_build,
|
build_context &bc, ProgramBuild &prog_build,
|
||||||
u32 lit_id,
|
u32 lit_id, const vector<RoseEdge> &lit_edges,
|
||||||
const vector<RoseEdge> &lit_edges) {
|
bool is_anchored_replay_program) {
|
||||||
RoseProgram program;
|
RoseProgram program;
|
||||||
|
|
||||||
// Check long literal info.
|
// Check long literal info.
|
||||||
@ -4794,6 +4791,11 @@ RoseProgram makeLitInitialProgram(const RoseBuildImpl &build,
|
|||||||
prog_build.floatingMinLiteralMatchOffset,
|
prog_build.floatingMinLiteralMatchOffset,
|
||||||
program);
|
program);
|
||||||
|
|
||||||
|
/* Check if we are able to deliever matches from the anchored table now */
|
||||||
|
if (!is_anchored_replay_program) {
|
||||||
|
makeAnchoredLiteralDelay(build, prog_build, lit_id, program);
|
||||||
|
}
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4806,7 +4808,13 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
|
|
||||||
DEBUG_PRINTF("lit id=%u, %zu lit edges\n", lit_id, lit_edges.size());
|
DEBUG_PRINTF("lit id=%u, %zu lit edges\n", lit_id, lit_edges.size());
|
||||||
|
|
||||||
RoseProgram program;
|
// Construct initial program up front, as its early checks must be able
|
||||||
|
// to jump to end and terminate processing for this literal.
|
||||||
|
auto lit_program = makeLitInitialProgram(build, bc, prog_build, lit_id,
|
||||||
|
lit_edges,
|
||||||
|
is_anchored_replay_program);
|
||||||
|
|
||||||
|
RoseProgram role_programs;
|
||||||
|
|
||||||
// Predecessor state id -> program block.
|
// Predecessor state id -> program block.
|
||||||
map<u32, RoseProgram> pred_blocks;
|
map<u32, RoseProgram> pred_blocks;
|
||||||
@ -4829,7 +4837,7 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
|
|
||||||
// Add blocks to deal with non-root edges (triggered by sparse iterator or
|
// Add blocks to deal with non-root edges (triggered by sparse iterator or
|
||||||
// mmbit_isset checks).
|
// mmbit_isset checks).
|
||||||
addPredBlocks(pred_blocks, bc.roleStateIndices.size(), program);
|
addPredBlocks(pred_blocks, bc.roleStateIndices.size(), role_programs);
|
||||||
|
|
||||||
// Add blocks to handle root roles.
|
// Add blocks to handle root roles.
|
||||||
for (const auto &e : lit_edges) {
|
for (const auto &e : lit_edges) {
|
||||||
@ -4839,31 +4847,23 @@ RoseProgram makeLiteralProgram(const RoseBuildImpl &build, build_context &bc,
|
|||||||
}
|
}
|
||||||
DEBUG_PRINTF("root edge (%zu,%zu)\n", g[u].index,
|
DEBUG_PRINTF("root edge (%zu,%zu)\n", g[u].index,
|
||||||
g[target(e, g)].index);
|
g[target(e, g)].index);
|
||||||
program.add_block(makeRoleProgram(build, bc, prog_build, e));
|
role_programs.add_block(makeRoleProgram(build, bc, prog_build, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lit_id == build.eod_event_literal_id) {
|
if (lit_id == build.eod_event_literal_id) {
|
||||||
|
/* Note: does not require the lit intial program */
|
||||||
assert(build.eod_event_literal_id != MO_INVALID_IDX);
|
assert(build.eod_event_literal_id != MO_INVALID_IDX);
|
||||||
return program;
|
return role_programs;
|
||||||
}
|
}
|
||||||
|
|
||||||
RoseProgram root_block;
|
/* Instructions to run even if a role program bails out */
|
||||||
|
RoseProgram unconditional_block;
|
||||||
|
|
||||||
// Literal may squash groups.
|
// Literal may squash groups.
|
||||||
makeGroupSquashInstruction(build, lit_id, root_block);
|
makeGroupSquashInstruction(build, lit_id, unconditional_block);
|
||||||
|
|
||||||
// Literal may be anchored and need to be recorded.
|
role_programs.add_block(move(unconditional_block));
|
||||||
if (!is_anchored_replay_program) {
|
lit_program.add_before_end(move(role_programs));
|
||||||
makeRecordAnchoredInstruction(build, prog_build, lit_id, root_block);
|
|
||||||
}
|
|
||||||
|
|
||||||
program.add_block(move(root_block));
|
|
||||||
|
|
||||||
// Construct initial program up front, as its early checks must be able
|
|
||||||
// to jump to end and terminate processing for this literal.
|
|
||||||
auto lit_program = makeLitInitialProgram(build, bc, prog_build, lit_id,
|
|
||||||
lit_edges);
|
|
||||||
lit_program.add_before_end(move(program));
|
|
||||||
|
|
||||||
return lit_program;
|
return lit_program;
|
||||||
}
|
}
|
||||||
|
@ -890,6 +890,7 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
|
|||||||
PROGRAM_CASE(ANCHORED_DELAY) {
|
PROGRAM_CASE(ANCHORED_DELAY) {
|
||||||
os << " groups 0x" << std::hex << ri->groups << std::dec
|
os << " groups 0x" << std::hex << ri->groups << std::dec
|
||||||
<< endl;
|
<< endl;
|
||||||
|
os << " anch_id " << ri->anch_id << "\n";
|
||||||
os << " done_jump " << offset + ri->done_jump << endl;
|
os << " done_jump " << offset + ri->done_jump << endl;
|
||||||
}
|
}
|
||||||
PROGRAM_NEXT_INSTRUCTION
|
PROGRAM_NEXT_INSTRUCTION
|
||||||
@ -1097,9 +1098,7 @@ void dumpProgram(ofstream &os, const RoseEngine *t, const char *pc) {
|
|||||||
}
|
}
|
||||||
PROGRAM_NEXT_INSTRUCTION
|
PROGRAM_NEXT_INSTRUCTION
|
||||||
|
|
||||||
PROGRAM_CASE(RECORD_ANCHORED) {
|
PROGRAM_CASE(DUMMY_NOP) {}
|
||||||
os << " id " << ri->id << endl;
|
|
||||||
}
|
|
||||||
PROGRAM_NEXT_INSTRUCTION
|
PROGRAM_NEXT_INSTRUCTION
|
||||||
|
|
||||||
PROGRAM_CASE(CATCH_UP) {}
|
PROGRAM_CASE(CATCH_UP) {}
|
||||||
|
@ -72,6 +72,7 @@ void RoseInstrAnchoredDelay::write(void *dest, RoseEngineBlob &blob,
|
|||||||
RoseInstrBase::write(dest, blob, offset_map);
|
RoseInstrBase::write(dest, blob, offset_map);
|
||||||
auto *inst = static_cast<impl_type *>(dest);
|
auto *inst = static_cast<impl_type *>(dest);
|
||||||
inst->groups = groups;
|
inst->groups = groups;
|
||||||
|
inst->anch_id = anch_id;
|
||||||
inst->done_jump = calc_jump(offset_map, this, target);
|
inst->done_jump = calc_jump(offset_map, this, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,13 +249,6 @@ void RoseInstrPushDelayed::write(void *dest, RoseEngineBlob &blob,
|
|||||||
inst->index = index;
|
inst->index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoseInstrRecordAnchored::write(void *dest, RoseEngineBlob &blob,
|
|
||||||
const OffsetMap &offset_map) const {
|
|
||||||
RoseInstrBase::write(dest, blob, offset_map);
|
|
||||||
auto *inst = static_cast<impl_type *>(dest);
|
|
||||||
inst->id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoseInstrSomAdjust::write(void *dest, RoseEngineBlob &blob,
|
void RoseInstrSomAdjust::write(void *dest, RoseEngineBlob &blob,
|
||||||
const OffsetMap &offset_map) const {
|
const OffsetMap &offset_map) const {
|
||||||
RoseInstrBase::write(dest, blob, offset_map);
|
RoseInstrBase::write(dest, blob, offset_map);
|
||||||
|
@ -216,18 +216,20 @@ class RoseInstrAnchoredDelay
|
|||||||
RoseInstrAnchoredDelay> {
|
RoseInstrAnchoredDelay> {
|
||||||
public:
|
public:
|
||||||
rose_group groups;
|
rose_group groups;
|
||||||
|
u32 anch_id;
|
||||||
const RoseInstruction *target;
|
const RoseInstruction *target;
|
||||||
|
|
||||||
RoseInstrAnchoredDelay(rose_group groups_in,
|
RoseInstrAnchoredDelay(rose_group groups_in, u32 anch_id_in,
|
||||||
const RoseInstruction *target_in)
|
const RoseInstruction *target_in)
|
||||||
: groups(groups_in), target(target_in) {}
|
: groups(groups_in), anch_id(anch_id_in), target(target_in) {}
|
||||||
|
|
||||||
bool operator==(const RoseInstrAnchoredDelay &ri) const {
|
bool operator==(const RoseInstrAnchoredDelay &ri) const {
|
||||||
return groups == ri.groups && target == ri.target;
|
return groups == ri.groups && anch_id == ri.anch_id
|
||||||
|
&& target == ri.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t hash() const override {
|
size_t hash() const override {
|
||||||
return hash_all(static_cast<int>(opcode), groups);
|
return hash_all(static_cast<int>(opcode), groups, anch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(void *dest, RoseEngineBlob &blob,
|
void write(void *dest, RoseEngineBlob &blob,
|
||||||
@ -235,8 +237,8 @@ public:
|
|||||||
|
|
||||||
bool equiv_to(const RoseInstrAnchoredDelay &ri, const OffsetMap &offsets,
|
bool equiv_to(const RoseInstrAnchoredDelay &ri, const OffsetMap &offsets,
|
||||||
const OffsetMap &other_offsets) const {
|
const OffsetMap &other_offsets) const {
|
||||||
return groups == ri.groups &&
|
return groups == ri.groups && anch_id == ri.anch_id
|
||||||
offsets.at(target) == other_offsets.at(ri.target);
|
&& offsets.at(target) == other_offsets.at(ri.target);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -844,32 +846,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RoseInstrRecordAnchored
|
|
||||||
: public RoseInstrBaseNoTargets<ROSE_INSTR_RECORD_ANCHORED,
|
|
||||||
ROSE_STRUCT_RECORD_ANCHORED,
|
|
||||||
RoseInstrRecordAnchored> {
|
|
||||||
public:
|
|
||||||
u32 id;
|
|
||||||
|
|
||||||
explicit RoseInstrRecordAnchored(u32 id_in) : id(id_in) {}
|
|
||||||
|
|
||||||
bool operator==(const RoseInstrRecordAnchored &ri) const {
|
|
||||||
return id == ri.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t hash() const override {
|
|
||||||
return hash_all(static_cast<int>(opcode), id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(void *dest, RoseEngineBlob &blob,
|
|
||||||
const OffsetMap &offset_map) const override;
|
|
||||||
|
|
||||||
bool equiv_to(const RoseInstrRecordAnchored &ri, const OffsetMap &,
|
|
||||||
const OffsetMap &) const {
|
|
||||||
return id == ri.id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class RoseInstrCatchUp
|
class RoseInstrCatchUp
|
||||||
: public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP, ROSE_STRUCT_CATCH_UP,
|
: public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP, ROSE_STRUCT_CATCH_UP,
|
||||||
RoseInstrCatchUp> {
|
RoseInstrCatchUp> {
|
||||||
@ -2281,6 +2257,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* \brief Adds this block to the program just before the terminating
|
* \brief Adds this block to the program just before the terminating
|
||||||
* ROSE_INSTR_END.
|
* ROSE_INSTR_END.
|
||||||
|
*
|
||||||
|
* Any existing instruction that was jumping to end continues to do so.
|
||||||
*/
|
*/
|
||||||
void add_before_end(RoseProgram &&block) {
|
void add_before_end(RoseProgram &&block) {
|
||||||
assert(!prog.empty());
|
assert(!prog.empty());
|
||||||
@ -2295,6 +2273,9 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Append this program block, replacing our current ROSE_INSTR_END.
|
* \brief Append this program block, replacing our current ROSE_INSTR_END.
|
||||||
|
*
|
||||||
|
* Any existing instruction that was jumping to end, now leads to the newly
|
||||||
|
* added block.
|
||||||
*/
|
*/
|
||||||
void add_block(RoseProgram &&block) {
|
void add_block(RoseProgram &&block) {
|
||||||
assert(!prog.empty());
|
assert(!prog.empty());
|
||||||
|
@ -62,7 +62,7 @@ enum RoseInstructionCode {
|
|||||||
ROSE_INSTR_CHECK_INFIX, //!< Infix engine 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_CHECK_PREFIX, //!< Prefix engine must be in accept state.
|
||||||
ROSE_INSTR_PUSH_DELAYED, //!< Push delayed literal matches.
|
ROSE_INSTR_PUSH_DELAYED, //!< Push delayed literal matches.
|
||||||
ROSE_INSTR_RECORD_ANCHORED, //!< Record an anchored literal match.
|
ROSE_INSTR_DUMMY_NOP, //!< NOP. Should not exist in build programs.
|
||||||
ROSE_INSTR_CATCH_UP, //!< Catch up engines, anchored matches.
|
ROSE_INSTR_CATCH_UP, //!< Catch up engines, anchored matches.
|
||||||
ROSE_INSTR_CATCH_UP_MPV, //!< Catch up the MPV.
|
ROSE_INSTR_CATCH_UP_MPV, //!< Catch up the MPV.
|
||||||
ROSE_INSTR_SOM_ADJUST, //!< Set SOM from a distance to EOM.
|
ROSE_INSTR_SOM_ADJUST, //!< Set SOM from a distance to EOM.
|
||||||
@ -188,7 +188,8 @@ struct ROSE_STRUCT_END {
|
|||||||
struct ROSE_STRUCT_ANCHORED_DELAY {
|
struct ROSE_STRUCT_ANCHORED_DELAY {
|
||||||
u8 code; //!< From enum RoseInstructionCode.
|
u8 code; //!< From enum RoseInstructionCode.
|
||||||
rose_group groups; //!< Bitmask.
|
rose_group groups; //!< Bitmask.
|
||||||
u32 done_jump; //!< Jump forward this many bytes if successful.
|
u32 anch_id; //!< Program to restart after the delay.
|
||||||
|
u32 done_jump; //!< Jump forward this many bytes if we have to delay.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ROSE_STRUCT_CHECK_LIT_EARLY {
|
struct ROSE_STRUCT_CHECK_LIT_EARLY {
|
||||||
@ -327,9 +328,8 @@ struct ROSE_STRUCT_PUSH_DELAYED {
|
|||||||
u32 index; // Delay literal index (relative to first delay lit).
|
u32 index; // Delay literal index (relative to first delay lit).
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ROSE_STRUCT_RECORD_ANCHORED {
|
struct ROSE_STRUCT_DUMMY_NOP {
|
||||||
u8 code; //!< From enum RoseInstructionCode.
|
u8 code; //!< From enum RoseInstructionCode.
|
||||||
u32 id; //!< Literal ID.
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ROSE_STRUCT_CATCH_UP {
|
struct ROSE_STRUCT_CATCH_UP {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user