polserver/pol-core/bscript/compiler/optimizer/CodeSectionOptimizer.cpp
turleypol 56ebd666e6
Fix ShortCircuit jump optimization corrupting assignments (#904)
* Fix ShortCircuit jump optimization corrupting assignments

The short-circuit jump optimizer threaded a logical jump past an
opposite-type logical jump (offset++). That target pops the value on
fall-through (Executor::ins_logical_jump), so skipping it left a stray
value on the stack, which corrupts a following stack-addressed assignment:

    var x := ( a && b ) || ( c && d );

left x uninitialized whenever the first clause was false (i.e. the
deciding clause is not the first operand). The same chain works as an
if() condition or when declaration and assignment are split
( var x; x := ... ).

Only thread same-type logical jumps; keep targeting opposite-type ones so
their fall-through pop still runs.

Adds testsuite/escript/opt/shortcircuit7 exercising the value / assignment
context (companion to shortcircuit6's if()-condition tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* removed other unsafe jump merges
additional test

* adapted testdata

* core changes xml

---------

Co-authored-by: Oleksii Rebreniuk <oleksii.rebreniuk@shopit.se>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 12:02:39 +02:00

36 lines
1.1 KiB
C++

#include "bscript/compiler/optimizer/CodeSectionOptimizer.h"
#include "bscript/StoredToken.h"
#include "bscript/compilercfg.h"
#include "bscript/tokens.h"
namespace Pol::Bscript::Compiler
{
void CodeSectionOptimizer::optimize( CodeSection& code ) const
{
if ( compilercfg.ShortCircuitEvaluation )
short_circuit_jumps( code );
}
void CodeSectionOptimizer::short_circuit_jumps( CodeSection& code ) const
{
// recursivly check if a logical jump would jump to another jump and update the final jump
// location
auto combine = [&]( StoredToken& jump, auto&& combine )
{
const auto& loc = code[jump.offset];
// logical jumps of different type pop value from stack
// same is true for "normal" jumps
// thus they cannot be optimized
if ( loc.id == INS_LOGICAL_JUMP && loc.type == jump.type )
jump.offset = loc.offset;
else if ( loc.id == INS_LOGICAL_CONVERT )
jump.offset++;
else
return;
return combine( jump, combine );
};
for ( auto& c : code )
if ( c.id == INS_LOGICAL_JUMP )
combine( c, combine );
}
} // namespace Pol::Bscript::Compiler