}
static
-void makeRoleAnchoredDelay(const RoseBuildImpl &build,
- u32 floatingMinLiteralMatchOffset,
- RoseVertex v, RoseProgram &program) {
- // Only relevant for roles that can be triggered by the anchored table.
- if (!build.isAnchored(v)) {
+void makeAnchoredLiteralDelay(const RoseBuildImpl &build,
+ const ProgramBuild &prog_build, u32 lit_id,
+ RoseProgram &program) {
+ // Only relevant for literals in the anchored table.
+ const rose_literal_id &lit = build.literals.right.at(lit_id);
+ if (lit.table != ROSE_ANCHORED) {
return;
}
- // If this match cannot occur after floatingMinLiteralMatchOffset, we do
- // not need this check.
- if (build.g[v].max_offset <= floatingMinLiteralMatchOffset) {
+ // If this literal match cannot occur after floatingMinLiteralMatchOffset,
+ // we do not need this check.
+ 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;
}
+ 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();
- 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));
}
// First, add program instructions that enforce preconditions without
// effects.
- makeRoleAnchoredDelay(build, prog_build.floatingMinLiteralMatchOffset, v,
- program);
-
if (onlyAtEod(build, v)) {
DEBUG_PRINTF("only at eod\n");
const auto *end_inst = program.end_instruction();
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
u32 findMinOffset(const RoseBuildImpl &build, u32 lit_id) {
const auto &lit_vertices = build.literal_info.at(lit_id).vertices;
static
RoseProgram makeLitInitialProgram(const RoseBuildImpl &build,
build_context &bc, ProgramBuild &prog_build,
- u32 lit_id,
- const vector<RoseEdge> &lit_edges) {
+ u32 lit_id, const vector<RoseEdge> &lit_edges,
+ bool is_anchored_replay_program) {
RoseProgram program;
// Check long literal info.
prog_build.floatingMinLiteralMatchOffset,
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;
}
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.
map<u32, RoseProgram> pred_blocks;
// Add blocks to deal with non-root edges (triggered by sparse iterator or
// mmbit_isset checks).
- addPredBlocks(pred_blocks, bc.roleStateIndices.size(), program);
+ addPredBlocks(pred_blocks, bc.roleStateIndices.size(), role_programs);
// Add blocks to handle root roles.
for (const auto &e : lit_edges) {
}
DEBUG_PRINTF("root edge (%zu,%zu)\n", g[u].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) {
+ /* Note: does not require the lit intial program */
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.
- makeGroupSquashInstruction(build, lit_id, root_block);
+ makeGroupSquashInstruction(build, lit_id, unconditional_block);
- // Literal may be anchored and need to be recorded.
- if (!is_anchored_replay_program) {
- 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));
+ role_programs.add_block(move(unconditional_block));
+ lit_program.add_before_end(move(role_programs));
return lit_program;
}
RoseInstrAnchoredDelay> {
public:
rose_group groups;
+ u32 anch_id;
const RoseInstruction *target;
- RoseInstrAnchoredDelay(rose_group groups_in,
+ RoseInstrAnchoredDelay(rose_group groups_in, u32 anch_id_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 {
- return groups == ri.groups && target == ri.target;
+ return groups == ri.groups && anch_id == ri.anch_id
+ && target == ri.target;
}
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,
bool equiv_to(const RoseInstrAnchoredDelay &ri, const OffsetMap &offsets,
const OffsetMap &other_offsets) const {
- return groups == ri.groups &&
- offsets.at(target) == other_offsets.at(ri.target);
+ return groups == ri.groups && anch_id == ri.anch_id
+ && offsets.at(target) == other_offsets.at(ri.target);
}
};
}
};
-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
: public RoseInstrBaseTrivial<ROSE_INSTR_CATCH_UP, ROSE_STRUCT_CATCH_UP,
RoseInstrCatchUp> {
/**
* \brief Adds this block to the program just before the terminating
* ROSE_INSTR_END.
+ *
+ * Any existing instruction that was jumping to end continues to do so.
*/
void add_before_end(RoseProgram &&block) {
assert(!prog.empty());
/**
* \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) {
assert(!prog.empty());
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_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_MPV, //!< Catch up the MPV.
ROSE_INSTR_SOM_ADJUST, //!< Set SOM from a distance to EOM.
struct ROSE_STRUCT_ANCHORED_DELAY {
u8 code; //!< From enum RoseInstructionCode.
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 {
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.
- u32 id; //!< Literal ID.
};
struct ROSE_STRUCT_CATCH_UP {