diff --git a/src/Debug/debugger.cpp b/src/Debug/debugger.cpp index 25df2957..0cb65b9b 100644 --- a/src/Debug/debugger.cpp +++ b/src/Debug/debugger.cpp @@ -24,6 +24,7 @@ Debugger::Debugger(Channel *duplex) { this->snapshotPolicy = SnapshotPolicy::none; this->checkpointInterval = 10; this->instructions_executed = 0; + this->instructions_since_full_snapshot = 0; this->fidx_called = {}; this->min_return_values = 0; this->checkpoint_state = nullptr; @@ -1015,6 +1016,7 @@ void Debugger::setSnapshotPolicy(Module *m, uint8_t *interruptData) { } checkpoint_state = nullptr; checkpoint_state_size = 0; + *data_ptr += 1; } else { snapshotPolicy = SnapshotPolicy::checkpointing; *data_ptr += 1; @@ -1032,8 +1034,9 @@ void Debugger::setSnapshotPolicy(Module *m, uint8_t *interruptData) { // Make a checkpoint when you first enable checkpointing if (snapshotPolicy == SnapshotPolicy::checkpointing) { - uint8_t *ptr = *data_ptr + 1; - checkpointInterval = read_B32(&ptr); + checkpointInterval = read_B32(data_ptr); + instructions_executed = 0; + instructions_since_full_snapshot = 0; checkpoint(m, true); } printf("ack%x\n", interruptSetSnapshotPolicy); @@ -1074,6 +1077,19 @@ void Debugger::handleSnapshotPolicy(Module *m) { } } } + + // When using tracing, optionally (if the interval is 0xffffffff no full + // snapshots will be taken) take full checkpoints every + // checkpointInterval instructions. + if (checkpoint_state != nullptr) { + if (checkpointInterval != UINT32_MAX && + instructions_since_full_snapshot >= checkpointInterval) { + checkpoint(m, true, true); + instructions_since_full_snapshot = 0; + } + instructions_since_full_snapshot++; + } + instructions_executed++; ExecutionContext *ectx = m->warduino->execution_context; @@ -1090,7 +1106,7 @@ void Debugger::handleSnapshotPolicy(Module *m) { } } -void Debugger::checkpoint(Module *m, const bool force) { +void Debugger::checkpoint(Module *m, const bool force, const bool full) { if (instructions_executed == 0 && !force) { return; } @@ -1119,7 +1135,7 @@ void Debugger::checkpoint(Module *m, const bool force) { this->channel->write("], "); } this->channel->write(R"("snapshot": )"); - if (!checkpoint_state) { + if (!checkpoint_state || full) { snapshot(m); } else { inspect(m, checkpoint_state_size, checkpoint_state); @@ -1142,6 +1158,11 @@ void Debugger::freeState(Module *m, uint8_t *interruptData) { ectx->sp = -1; memset(ectx->br_table, 0, BR_TABLE_SIZE); + // Reset checkpointing counters, new checkpoints will have instructions + // executed since this snapshot. + instructions_since_full_snapshot = 0; + instructions_executed = 0; + while (first_msg < endfm) { switch (*first_msg++) { case globalsState: { @@ -1661,6 +1682,7 @@ bool Debugger::handleUpdateStackValue(const Module *m, uint8_t *bytes) const { bool Debugger::reset(Module *m) { m->warduino->reset_module(m); instructions_executed = 0; + instructions_since_full_snapshot = 0; this->channel->write("Reset WARDuino.\n"); return true; } diff --git a/src/Debug/debugger.h b/src/Debug/debugger.h index 6a241ab8..3a5b6626 100644 --- a/src/Debug/debugger.h +++ b/src/Debug/debugger.h @@ -155,8 +155,10 @@ class Debugger { // Checkpointing SnapshotPolicy snapshotPolicy; - uint32_t checkpointInterval; // #instructions between checkpoints - uint32_t instructions_executed; // #instructions since last checkpoint + uint32_t checkpointInterval; // #instructions between checkpoints + uint32_t instructions_executed; // #instructions since last checkpoint + uint32_t instructions_since_full_snapshot; // #instructions since last full + // snapshot std::optional fidx_called; // The primitive that was executed uint32_t prim_args[8]; // The arguments of the executed prim uint32_t min_return_values; @@ -336,6 +338,6 @@ class Debugger { bool getMockForArgs(Module *m, uint32_t fidx, uint32_t &result); // Checkpointing - void checkpoint(Module *m, bool force = false); + void checkpoint(Module *m, bool force = false, bool full = false); inline SnapshotPolicy getSnapshotPolicy() { return snapshotPolicy; } };