Skip to content

Commit 4b6572c

Browse files
committed
VirtualMachine: Do not use function calls for loops
1 parent 8e1c813 commit 4b6572c

File tree

2 files changed

+43
-15
lines changed

2 files changed

+43
-15
lines changed

src/engine/virtualmachine.cpp

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ VirtualMachine::VirtualMachine(Target *target, Engine *engine) :
3636
m_regs = new Value *[MAX_REG_COUNT];
3737
for (int i = 0; i < MAX_REG_COUNT; i++)
3838
m_regs[i] = new Value();
39+
m_loops.reserve(256);
3940
}
4041

4142
/*! Destroys the VirtualMachine object. */
@@ -192,35 +193,54 @@ unsigned int *VirtualMachine::run(unsigned int *pos)
192193
loopEnd = pos;
193194
while (*loopEnd != OP_LOOP_END)
194195
loopEnd += instruction_arg_count[*loopEnd++];
196+
pos = loopEnd;
195197
} else {
196-
for (size_t i = 0; i < loopCount; i++)
197-
loopEnd = run(pos);
198+
Loop l;
199+
l.isRepeatLoop = true;
200+
l.start = pos;
201+
l.index = 0;
202+
l.max = loopCount;
203+
m_loops.push_back(l);
198204
}
199-
pos = loopEnd;
200205
DISPATCH();
201206

202207
do_until_loop:
203208
loopStart = run(pos);
204209
if (!READ_LAST_REG()->toBool()) {
205-
do {
206-
FREE_REGS(1);
207-
loopEnd = run(loopStart);
208-
run(pos);
209-
} while (!READ_LAST_REG()->toBool());
210-
FREE_REGS(1);
210+
Loop l;
211+
l.isRepeatLoop = false;
212+
l.start = pos;
213+
m_loops.push_back(l);
214+
pos = loopStart;
211215
} else {
212-
loopEnd = loopStart;
213-
while (*loopEnd != OP_LOOP_END)
214-
loopEnd += instruction_arg_count[*loopEnd++];
216+
pos = loopStart;
217+
while (*pos != OP_LOOP_END)
218+
pos += instruction_arg_count[*pos++];
215219
}
216-
pos = loopEnd;
220+
FREE_REGS(1);
217221
DISPATCH();
218222

219223
do_begin_until_loop:
220224
return pos;
221225

222-
do_loop_end:
223-
return pos;
226+
do_loop_end : {
227+
Loop &l = m_loops.back();
228+
if (l.isRepeatLoop) {
229+
if (++l.index < l.max)
230+
pos = l.start;
231+
else
232+
m_loops.pop_back();
233+
DISPATCH();
234+
} else {
235+
loopStart = run(l.start);
236+
if (!READ_LAST_REG()->toBool())
237+
pos = loopStart;
238+
else
239+
m_loops.pop_back();
240+
FREE_REGS(1);
241+
DISPATCH();
242+
}
243+
}
224244

225245
do_print:
226246
std::cout << READ_LAST_REG()->toString() << std::endl;

src/engine/virtualmachine.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,20 @@ class LIBSCRATCHCPP_EXPORT VirtualMachine
114114
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1
115115
};
116116

117+
typedef struct
118+
{
119+
bool isRepeatLoop;
120+
unsigned int *start;
121+
size_t index, max;
122+
} Loop;
123+
117124
unsigned int *m_bytecode;
118125
std::vector<unsigned int> m_bytecodeVector;
119126

120127
Target *m_target = nullptr;
121128
Engine *m_engine = nullptr;
122129
bool m_atEnd = false;
130+
std::vector<Loop> m_loops;
123131

124132
BlockFunc *m_functions;
125133
std::vector<BlockFunc> m_functionsVector;

0 commit comments

Comments
 (0)