@@ -115,7 +115,7 @@ VirtualMachinePrivate::~VirtualMachinePrivate()
115115 delete regs;
116116}
117117
118- unsigned int *VirtualMachinePrivate::run (unsigned int *pos)
118+ unsigned int *VirtualMachinePrivate::run (unsigned int *pos, bool reset )
119119{
120120 static const void *dispatch_table[] = {
121121 nullptr ,
@@ -186,9 +186,11 @@ unsigned int *VirtualMachinePrivate::run(unsigned int *pos)
186186 unsigned int *loopStart;
187187 unsigned int *loopEnd;
188188 size_t loopCount;
189- atEnd = false ;
190- atomic = true ;
191- warp = false ;
189+ if (reset) {
190+ atEnd = false ;
191+ atomic = true ;
192+ warp = false ;
193+ }
192194 DISPATCH ();
193195
194196do_halt:
@@ -279,7 +281,7 @@ do_repeat_loop_index1 : {
279281}
280282
281283do_until_loop:
282- loopStart = run (pos);
284+ loopStart = run (pos, false );
283285 if (!READ_LAST_REG ()->toBool ()) {
284286 Loop l;
285287 l.isRepeatLoop = false ;
@@ -314,7 +316,7 @@ do_loop_end : {
314316 engine->breakFrame ();
315317 return pos - 1 ;
316318 }
317- loopStart = run (l.start );
319+ loopStart = run (l.start , false );
318320 if (!READ_LAST_REG ()->toBool ())
319321 pos = loopStart;
320322 else
@@ -330,31 +332,26 @@ do_loop_end : {
330332 DISPATCH ();
331333
332334do_add:
333- REPLACE_RET_VALUE (*READ_REG (0 , 2 ), 2 );
334335 READ_REG (0 , 2 )->add (*READ_REG (1 , 2 ));
335336 FREE_REGS (1 );
336337 DISPATCH ();
337338
338339do_subtract:
339- REPLACE_RET_VALUE (*READ_REG (0 , 2 ), 2 );
340340 READ_REG (0 , 2 )->subtract (*READ_REG (1 , 2 ));
341341 FREE_REGS (1 );
342342 DISPATCH ();
343343
344344do_multiply:
345- REPLACE_RET_VALUE (*READ_REG (0 , 2 ), 2 );
346345 READ_REG (0 , 2 )->multiply (*READ_REG (1 , 2 ));
347346 FREE_REGS (1 );
348347 DISPATCH ();
349348
350349do_divide:
351- REPLACE_RET_VALUE (*READ_REG (0 , 2 ), 2 );
352350 READ_REG (0 , 2 )->divide (*READ_REG (1 , 2 ));
353351 FREE_REGS (1 );
354352 DISPATCH ();
355353
356354do_mod:
357- REPLACE_RET_VALUE (*READ_REG (0 , 2 ), 2 );
358355 READ_REG (0 , 2 )->mod (*READ_REG (1 , 2 ));
359356 FREE_REGS (1 );
360357 DISPATCH ();
@@ -651,10 +648,16 @@ do_list_get_item : {
651648 FREE_REGS (1 );
652649 DISPATCH ();
653650
654- do_str_at:
655- REPLACE_RET_VALUE (READ_REG (0 , 2 )->toUtf16 ()[READ_REG (1 , 2 )->toLong ()], 2 );
651+ do_str_at : {
652+ size_t index = READ_REG (1 , 2 )->toLong () - 1 ;
653+ std::u16string str = READ_REG (0 , 2 )->toUtf16 ();
654+ if (index < 0 || index >= str.size ())
655+ REPLACE_RET_VALUE (" " , 2 );
656+ else
657+ REPLACE_RET_VALUE (utf8::utf16to8 (std::u16string ({ str[index] })), 2 );
656658 FREE_REGS (1 );
657659 DISPATCH ();
660+ }
658661
659662do_str_length:
660663 REPLACE_RET_VALUE (static_cast <long >(READ_REG (0 , 1 )->toUtf16 ().size ()), 1 );
@@ -668,7 +671,7 @@ do_list_get_item : {
668671do_exec : {
669672 auto ret = functions[*++pos](vm);
670673 if (updatePos) {
671- pos = pos;
674+ pos = this -> pos ;
672675 updatePos = false ;
673676 }
674677 if (stop) {
@@ -677,17 +680,16 @@ do_exec : {
677680 procedureArgTree.clear ();
678681 procedureArgs = nullptr ;
679682 nextProcedureArgs = nullptr ;
680- if (!atomic && !warp )
683+ if (!atomic)
681684 engine->breakFrame ();
682685 if (goBack) {
683686 goBack = false ;
684687 pos -= instruction_arg_count[OP_EXEC] + 1 ;
688+ // NOTE: Going back leaks all registers for the next time the same function is called.
689+ // This is for example used in the wait block (to call it again with the same time value).
685690 } else
686691 FREE_REGS (ret);
687- if (warp)
688- DISPATCH ();
689- else
690- return pos;
692+ return pos;
691693 }
692694 FREE_REGS (ret);
693695 DISPATCH ();
0 commit comments