Skip to content

Commit f02942e

Browse files
committed
VirtualMachine: Add checkpoints
1 parent ee97085 commit f02942e

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

src/engine/virtualmachine.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const unsigned int VirtualMachine::instruction_arg_count[] = {
3030
0, // OP_HALT
3131
1, // OP_CONST
3232
0, // OP_NULL
33+
0, // OP_CHECKPOINT
3334
0, // OP_IF
3435
0, // OP_ELSE
3536
0, // OP_ENDIF
@@ -168,13 +169,22 @@ void VirtualMachine::reset()
168169
m_pos = m_bytecode;
169170
}
170171

172+
/*! Moves back to the last vm::OP_CHECKPOINT instruction in the bytecode. */
173+
void VirtualMachine::moveToLastCheckpoint()
174+
{
175+
assert(m_checkpoint);
176+
m_pos = m_checkpoint;
177+
m_updatePos = true;
178+
}
179+
171180
unsigned int *VirtualMachine::run(unsigned int *pos)
172181
{
173182
static const void *dispatch_table[] = {
174183
nullptr,
175184
&&do_halt,
176185
&&do_const,
177186
&&do_null,
187+
&&do_checkpoint,
178188
&&do_if,
179189
&&do_else,
180190
&&do_endif,
@@ -267,6 +277,10 @@ unsigned int *VirtualMachine::run(unsigned int *pos)
267277
ADD_RET_VALUE(Value());
268278
DISPATCH();
269279

280+
do_checkpoint:
281+
m_checkpoint = pos - 1;
282+
DISPATCH();
283+
270284
do_if:
271285
if (!READ_LAST_REG()->toBool()) {
272286
while (*pos != OP_ELSE && *pos != OP_ENDIF)
@@ -687,6 +701,10 @@ do_list_get_item : {
687701

688702
do_exec : {
689703
auto ret = m_functions[*++pos](this);
704+
if (m_updatePos) {
705+
pos = m_pos;
706+
m_updatePos = false;
707+
}
690708
if (m_stop) {
691709
m_stop = false;
692710
m_callTree.clear();

src/engine/virtualmachine.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ enum Opcode
1919
OP_HALT, /*!< The last instruction of every bytecode. */
2020
OP_CONST, /*!< Adds a constant value with the index in the argument to the next register. */
2121
OP_NULL, /*!< Adds a null (zero) value to the next register. */
22+
OP_CHECKPOINT, /*!< A checkpoint for the VirtualMachine::moveToLastCheckpoint() method. */
2223
OP_IF, /*!< Jumps to the next instruction if the last register holds "true". If it's false, jumps to OP_ELSE or OP_ENDIF. */
2324
OP_ELSE, /*!< Jumps to OP_ENDIF. This instruction is typically reached when the if statement condition was "true". */
2425
OP_ENDIF, /*!< Doesn't do anything, but is used by OP_IF and OP_ELSE. */
@@ -113,6 +114,7 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
113114

114115
void run();
115116
void reset();
117+
void moveToLastCheckpoint();
116118

117119
/*!
118120
* Use this to stop the script from a function.
@@ -156,6 +158,7 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
156158
Engine *m_engine = nullptr;
157159
Script *m_script = nullptr;
158160
unsigned int *m_pos = nullptr;
161+
unsigned int *m_checkpoint = nullptr;
159162
bool m_atEnd = false;
160163
std::vector<Loop> m_loops;
161164
std::vector<unsigned int *> m_callTree;
@@ -168,6 +171,7 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
168171
bool m_savePos = true;
169172
bool m_goBack = false;
170173
unsigned int m_freeExecRegs;
174+
bool m_updatePos = false;
171175

172176
unsigned int **m_procedures = nullptr;
173177
BlockFunc *m_functions;

0 commit comments

Comments
 (0)