Skip to content

JIT: ir_save assertion ((ref) < 0) failed when dumping IR with opcache.jit_debug on a foreach loop #24397

Open

Description

@waroad

With a debug build, dumping the JIT IR via opcache.jit_debug aborts in ir_save() on a function containing a foreach. The script was generated by a testing tool, not taken from a real program.

<?php
function f() { foreach ([1, 2] as $v) $c[] = $v; }
f();
php -n -d opcache.enable_cli=1 -d opcache.file_update_protection=0 -d opcache.jit=function -d opcache.jit_buffer_size=64M -d opcache.jit_debug=16777216 reduced.php

The IR text is printed up to a BEGIN node, then:

	l_88 = LOOP_END(l_87);
	l_89 = BEGIN(l_36php: ext/opcache/jit/ir/ir_save.c:397: ir_save: Assertion `((ref) < 0)' failed.

I expected the full IR dump to be printed and the process to exit 0, which is what the release build does with the same command.

Reproduces at 17b6575 (latest upstream when checked). The debug build aborts with SIGABRT (exit 134); the release build prints the whole dump and exits 0, so this is an assertion-only failure. Without opcache.jit_debug the debug build runs the script cleanly. Any of the IR dump bits 1<<24 to 1<<31 trigger it; the tracing JIT with the same bit did not fail on this input.

This looks like ir_save() in ext/opcache/jit/ir/ir_save.c (case IR_OPND_LABEL_REF) assuming a non-zero label operand is a constant (negative) ref, while the BEGIN node of the foreach loop has an instruction (positive) ref there. Either the IR builder or the dumper's assumption is off.

I can send a patch if that helps.

Found with an LLM-based testing tool; I used Claude to reduce it and look for the cause.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions