Skip to content

Commit df198ff

Browse files
committed
fix #498: Store a tree of running loop count
1 parent b2850b4 commit df198ff

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

src/engine/virtualmachine_p.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ VirtualMachinePrivate::VirtualMachinePrivate(VirtualMachine *vm, Target *target,
121121
regs = regsVector.data();
122122
loops.reserve(256);
123123
callTree.reserve(1024);
124+
loopCountTree.reserve(1024);
124125

125126
if (!rng)
126127
rng = RandomGenerator::instance().get();
@@ -233,10 +234,19 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset)
233234
warp = oldState.second;
234235
callTree.pop_back();
235236
procedureArgTree.pop_back();
237+
236238
if (procedureArgTree.empty())
237239
procedureArgs = nullptr;
238240
else
239241
procedureArgs = &procedureArgTree.back();
242+
243+
int loopsToRemove = loops.size() - loopCountTree.back();
244+
assert(loopsToRemove >= 0);
245+
loopCountTree.pop_back();
246+
247+
for (int i = 0; i < loopsToRemove; i++)
248+
loops.pop_back();
249+
240250
DISPATCH();
241251
}
242252

@@ -807,6 +817,7 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos, bool reset)
807817
callTree.push_back({ ++pos, warp });
808818
procedureArgs = nextProcedureArgs;
809819
nextProcedureArgs = nullptr;
820+
loopCountTree.push_back(loops.size());
810821
pos = procedurePos;
811822
} else
812823
pos++;

src/engine/virtualmachine_p.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ struct VirtualMachinePrivate
5050
std::vector<std::vector<Value>> procedureArgTree;
5151
std::vector<Value> *procedureArgs = nullptr;
5252
std::vector<Value> *nextProcedureArgs = nullptr;
53+
std::vector<unsigned int> loopCountTree;
5354
bool noBreak = true;
5455
bool warp = false;
5556
bool stop = false;

test/virtual_machine/virtual_machine_test.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,3 +1794,23 @@ TEST(VirtualMachineTest, StopAfterKilled)
17941794
ASSERT_TRUE(vm.atEnd());
17951795
ASSERT_EQ(vm.registerCount(), 0);
17961796
}
1797+
1798+
TEST(VirtualMachineTest, NoCrashAfterCallingProcedureFromLoop)
1799+
{
1800+
// Regtest for #498
1801+
static unsigned int bytecode[] = { OP_START, OP_CONST, 0, OP_REPEAT_LOOP, OP_INIT_PROCEDURE, OP_CONST, 1, OP_ADD_ARG, OP_CALL_PROCEDURE, 0, OP_LOOP_END, OP_HALT };
1802+
static unsigned int procedure[] = { OP_START, OP_WARP, OP_CONST, 0, OP_REPEAT_LOOP, OP_READ_ARG, 0, OP_PRINT, OP_HALT, OP_LOOP_END, OP_HALT };
1803+
static unsigned int *procedures[] = { procedure };
1804+
static Value constValues[] = { 2, "test" };
1805+
1806+
VirtualMachine vm;
1807+
vm.setBytecode(bytecode);
1808+
vm.setProcedures(procedures);
1809+
vm.setConstValues(constValues);
1810+
1811+
::testing::internal::CaptureStdout();
1812+
vm.run();
1813+
ASSERT_TRUE(vm.atEnd());
1814+
ASSERT_EQ(vm.registerCount(), 0);
1815+
ASSERT_EQ(::testing::internal::GetCapturedStdout(), "test\ntest\n");
1816+
}

0 commit comments

Comments
 (0)