Skip to content

CPPIA JIT: dynamic-array resize evaluates the receiver twice and can resize the wrong array #411

Open

Description

@dimensionscape

The JIT evaluates the receiver twice for Array<Dynamic>.resize() and cpp.NativeArray.setSize(). A receiver with side effects runs twice, and if it returns a different array on its second call, the operation resizes that second array.

class Script {
    static var calls = 0;
    static var first:Array<Dynamic> = [1, "two", 3];
    static var second:Array<Dynamic> = [4, "five", 6];
    static function receiver():Array<Dynamic> {
        calls++;
        return calls == 1 ? first : second;
    }
    static function main() {
        receiver().resize(1);
        Sys.println('calls=$calls first=$first second=$second');
    }
}

Native C++ and Haxe Eval print:

calls=1 first=[1] second=[4,five,6]

The CPPIA JIT prints:

calls=2 first=[1,two,3] second=[4]

Replacing receiver().resize(1) with cpp.NativeArray.setSize(receiver(), 1) reproduces the same wrong-array mutation under the JIT. The interpreter calls that receiver once and resizes first correctly. Interpreter resize has a separate missing-dispatch bug, so it is not a passing control for that operation.

ArrayBuiltinAny::genCode generates thisExpr before its switch for every operation except afBlit. The af__SetSizeExact and afResize branches each declare another thisVal and generate thisExpr again. Reuse the already evaluated receiver or exclude these branches from the initial evaluation.

Reproduced on Windows x64, Haxe 4.3.7, MSVC 19.44, libhxcpp 4cdca96, release host with -D scriptable --dce no -D HXCPP_M64. The host selects the engine with cpp.cppia.Host.enableJit(false/true) before Host.runFile. Native C++ controls use the same runtime checkout. Current main at 5f7cfef has the same ArrayVirtual.cpp.

Local regression fixture: test/regression/CppiaDynamicResizeReceiver/{Script.hx,Main.hx,build.hxml,stdout.txt}. It checks receiver counts and both arrays for both operations under both engines. The fixture is uncommitted; no runtime fix is included.

This concerns receiver evaluation and the mutation target, separate from the exception propagation reported in #404.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions