Skip to content

_ir_RSTORE: Assertion `ctx->control' failed #15101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
TRowbotham opened this issue Jul 24, 2024 · 3 comments
Closed

_ir_RSTORE: Assertion `ctx->control' failed #15101

TRowbotham opened this issue Jul 24, 2024 · 3 comments

Comments

@TRowbotham
Copy link
Contributor

Description

I am hitting an assertion failure in the JIT using PHP 8.4.0alpha2 in a particular project. I have not yet been able to create a small reproducer, so hopefully the following stack trace is useful.

Relevant changed ini settings:
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.jit=1255
opcache.jit_buffer_size=256M

php: /home/trevor/.phpbrew/build/php-8.4.0alpha2/ext/opcache/jit/ir/ir.c:2810: _ir_RSTORE: Assertion `ctx->control' failed.

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737294845440) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737294845440) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737294845440) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737294845440, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff73e5476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff73cb7f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff73cb71b in __assert_fail_base (fmt=0x7ffff7580130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
    assertion=0x7ffff40e7e63 "ctx->control",
    file=0x7ffff40e3ba0 "/home/trevor/.phpbrew/build/php-8.4.0alpha2/ext/opcache/jit/ir/ir.c", line=2810,
    function=<optimized out>) at ./assert/assert.c:92
#6  0x00007ffff73dce96 in __GI___assert_fail (assertion=0x7ffff40e7e63 "ctx->control",
    file=0x7ffff40e3ba0 "/home/trevor/.phpbrew/build/php-8.4.0alpha2/ext/opcache/jit/ir/ir.c", line=2810,
    function=0x7ffff40e8700 <__PRETTY_FUNCTION__.7> "_ir_RSTORE") at ./assert/assert.c:101
#7  0x00007ffff4029220 in _ir_RSTORE (ctx=0x7fffffff1900, reg=15, val=-90)
    at /home/trevor/.phpbrew/build/php-8.4.0alpha2/ext/opcache/jit/ir/ir.c:2810
#8  0x00007ffff3f9416e in jit_STORE_IP (jit=0x7fffffff1900, ref=-90) at ext/opcache/jit/zend_jit_ir.c:905
#9  0x00007ffff3f945b1 in zend_jit_set_ip (jit=0x7fffffff1900, target=0x555536471cb0)
    at ext/opcache/jit/zend_jit_ir.c:1040
#10 0x00007ffff3fce0c2 in zend_jit_trace_handler (jit=0x7fffffff1900, op_array=0x5555364823e8, opline=0x555536471cb0,
    may_throw=1, trace=0x7fffffff71c0) at ext/opcache/jit/zend_jit_ir.c:16410
#11 0x00007ffff4006579 in zend_jit_trace (trace_buffer=0x7fffffff6ef0, parent_trace=655, exit_num=5)
    at ext/opcache/jit/zend_jit_trace.c:6353
#12 0x00007ffff400fc49 in zend_jit_compile_side_trace (trace_buffer=0x7fffffff6ef0, parent_num=655, exit_num=5,
    polymorphism=1) at ext/opcache/jit/zend_jit_trace.c:8192
#13 0x00007ffff4010ae6 in zend_jit_trace_hot_side (execute_data=0x7ffff4418130, parent_num=655, exit_num=5)
    at ext/opcache/jit/zend_jit_trace.c:8413
#14 0x00007ffff40121b7 in zend_jit_trace_exit (exit_num=5, regs=0x7fffffffb040)
    at ext/opcache/jit/zend_jit_trace.c:8682
#15 0x0000555545400620 in ?? ()
#16 0x00005555364822e8 in ?? ()
--Type <RET> for more, q to quit, c to continue without paging--c
#17 0x00005555364a1888 in ?? ()
#18 0x00007ffff3d9dfa0 in ?? ()
#19 0x0000555536bc3a30 in ?? ()
#20 0x00007fffffffb150 in ?? ()
#21 0x00007fffffffb3a0 in ?? ()
#22 0x000055553570c490 in ?? ()
#23 0x00007fffef0f09b0 in ?? ()
#24 0x0000555555dd0365 in zend_abstract_method_call (fbc=0x7fffef0f09b0) at /home/trevor/.phpbrew/build/php-8.4.0alpha2/Zend/zend_object_handlers.c:1640
#25 0x0000000000000000 in ?? ()

PHP Version

PHP 8.4.0alpha2

Operating System

Ubuntu 22.04

@dstogov
Copy link
Member

dstogov commented Jul 25, 2024

Could you please reproduce this with -d opcache.jit_debug=0x1ff000 and paste information about the last compiled trace (the related PHP code would be also useful).

@TRowbotham
Copy link
Contributor Author

---- TRACE 640 start (side trace 582/14) Rowbot\DOM\Parser\Collection\ObjectStack::isEmpty() /home/trevor/GitHub/PHPJS/src/Parser/Collection/ObjectStack.php:55
0002 RETURN T0 ; op1(bool)
---- TRACE 640 stop (return)
---- TRACE 640 TSSA start (side trace 582/14) Rowbot\DOM\Parser\Collection\ObjectStack::isEmpty() /home/trevor/GitHub/PHPJS/src/Parser/Collection/ObjectStack.php:55
     ;#0.X0 [!true]
0002 RETURN #0.T0 [!true] ; op1(bool)
---- TRACE 640 TSSA stop (return)
---- TRACE 640 exit info
     exit_0: 0002/0000/2 X1:int
---- TRACE 640 compiled

     TRACE 588 exit 4 Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processToken() /home/trevor/GitHub/PHPJS/src/Parser/HTML/InsertionMode/InitialInsertionMode.php:54
---- TRACE 641 start (side trace 588/4) Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processToken() /home/trevor/GitHub/PHPJS/src/Parser/HTML/InsertionMode/InitialInsertionMode.php:54
0037 INIT_METHOD_CALL 2 THIS string("processDoctypeToken")
     >init Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processDoctypeToken
0038 SEND_VAR CV0($context) 1 ; op1(object of class Rowbot\DOM\Parser\HTML\TreeBuilderContext)
0039 SEND_VAR CV1($token) 2 ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken)
0040 DO_FCALL
     >enter Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processDoctypeToken
0000  CV0($context) = RECV 1
0001  CV1($token) = RECV 2
0002  CV2($publicId) = FETCH_OBJ_R CV1($token) string("publicIdentifier") ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken) val(null)
0003  CV3($systemId) = FETCH_OBJ_R CV1($token) string("systemIdentifier") ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken) val(null)
0004  CV4($name) = FETCH_OBJ_R CV1($token) string("name") ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken) val(string)
0005  T6 = IS_NOT_IDENTICAL CV4($name) string("html") ; op1(string)
0006  ;JMPNZ T6 0011
0007  T6 = TYPE_CHECK TYPE [bool, long, double, string, array, object, resource] CV2($publicId) ; op1(null)
0008  ;JMPNZ T6 0011
0009  T6 = TYPE_CHECK TYPE [bool, long, double, string, array, object, resource] CV3($systemId) ; op1(null)
0010  ;JMPZ T6 0011
0011  V6 = NEW 4 string("Rowbot\\DOM\\DocumentType")
      >init Rowbot\DOM\DocumentType::__construct
0012  CHECK_FUNC_ARG 1
0013  V7 = FETCH_OBJ_FUNC_ARG (ref) CV0($context) string("document") ; op1(object of class Rowbot\DOM\Parser\HTML\TreeBuilderContext) val(object)
0014  SEND_FUNC_ARG V7 1 ; op1(object of class Rowbot\DOM\HTMLDocument)
0015  T7 = COALESCE CV4($name) 0017 ; op1(string)
0017  SEND_VAL_EX T7 2 ; op1(string)
0018  T7 = COALESCE CV2($publicId) 0020 ; op1(null)
0019  T7 = QM_ASSIGN string("")
0020  SEND_VAL_EX T7 3 ; op1(string)
0021  T7 = COALESCE CV3($systemId) 0023 ; op1(null)
0022  T7 = QM_ASSIGN string("")
0023  SEND_VAL_EX T7 4 ; op1(string)
0024  DO_FCALL
      >enter Rowbot\DOM\DocumentType::__construct
0000   CV0($document) = RECV 1
0001   CV1($name) = RECV 2
0002   CV2($publicId) = RECV_INIT 3 string("")
0003   ;CV3($systemId) = RECV_INIT 4 string("")
0004   INIT_STATIC_METHOD_CALL 2 (parent) (exception) CONSTRUCTOR
       >init Rowbot\DOM\Node::__construct
0005   SEND_VAR_EX CV0($document) 1 ; op1(object of class Rowbot\DOM\HTMLDocument)
0006   T4 = FETCH_CLASS_CONSTANT (self) (exception) string("DOCUMENT_TYPE_NODE")
0007   SEND_VAL_EX T4 2 ; op1(int)
0008   DO_FCALL
       >enter Rowbot\DOM\Node::__construct
---- TRACE 641 stop (link to 77)
---- TRACE 641 TSSA start (side trace 588/4) Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processToken() /home/trevor/GitHub/PHPJS/src/Parser/HTML/InsertionMode/InitialInsertionMode.php:54
     ;#0.CV0($context) [rc1, rcn, object]
     ;#1.CV1($token) [rc1, rcn, object]
0037 INIT_METHOD_CALL 2 THIS string("processDoctypeToken")
     >init Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processDoctypeToken
0038 SEND_VAR #0.CV0($context) [rc1, rcn, object] -> #5.CV0($context) NOVAL [rc1, rcn, object] 1 ; op1(object of class Rowbot\DOM\Parser\HTML\TreeBuilderContext)
0039 SEND_VAR #1.CV1($token) [rc1, rcn, object] -> #6.CV1($token) NOVAL [rc1, rcn, object] 2 ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken)
0040 DO_FCALL
     >enter Rowbot\DOM\Parser\HTML\InsertionMode\InitialInsertionMode::processDoctypeToken
      ;#9.CV2($publicId) NOVAL [undef]
      ;#10.CV3($systemId) NOVAL [undef]
      ;#11.CV4($name) NOVAL [undef]
0000  #13.CV0($context) [rc1, rcn, object] = RECV 1
0001  #14.CV1($token) [rc1, rcn, object] = RECV 2
0002  FETCH_OBJ_R #14.CV1($token) [rc1, rcn, object] string("publicIdentifier") #9.CV2($publicId) NOVAL [undef] -> #15.CV2($publicId) [!null] ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken) val(null)
0003  FETCH_OBJ_R #14.CV1($token) [rc1, rcn, object] string("systemIdentifier") #10.CV3($systemId) NOVAL [undef] -> #16.CV3($systemId) [!null] ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken) val(null)
0004  FETCH_OBJ_R #14.CV1($token) [rc1, rcn, object] string("name") #11.CV4($name) NOVAL [undef] -> #17.CV4($name) [!rc1, rcn, string] ; op1(object of class Rowbot\DOM\Parser\Token\DoctypeToken) val(string)
0005  #18.T6 [bool] = IS_NOT_IDENTICAL #17.CV4($name) [!rc1, rcn, string] string("html") ; op1(string)
0006  ;JMPNZ #18.T6 [bool] 0011
0007  #19.T6 [false] = TYPE_CHECK TYPE [bool, long, double, string, array, object, resource] #15.CV2($publicId) [!null] ; op1(null)
0008  ;JMPNZ #19.T6 [false] 0011
0009  #20.T6 [false] = TYPE_CHECK TYPE [bool, long, double, string, array, object, resource] #16.CV3($systemId) [!null] ; op1(null)
0010  ;JMPZ #20.T6 [false] 0011
0011  #21.V6 [rc1, rcn, object] = NEW 4 string("Rowbot\\DOM\\DocumentType")
      >init Rowbot\DOM\DocumentType::__construct
0012  CHECK_FUNC_ARG 1
0013  #22.V7 [!rc1, rcn, object] = FETCH_OBJ_FUNC_ARG (ref) #13.CV0($context) [rc1, rcn, object] string("document") ; op1(object of class Rowbot\DOM\Parser\HTML\TreeBuilderContext) val(object)
0014  SEND_FUNC_ARG #22.V7 [!rc1, rcn, object] 1 ; op1(object of class Rowbot\DOM\HTMLDocument)
0015  #24.T7 [rc1, rcn, string] = COALESCE #17.CV4($name) [!rc1, rcn, string] -> #23.CV4($name) [rc1, rcn, string] 0017 ; op1(string)
0017  SEND_VAL_EX #24.T7 [rc1, rcn, string] 2 ; op1(string)
0018  #26.T7 [] = COALESCE #15.CV2($publicId) [!null] -> #25.CV2($publicId) [null] 0020 ; op1(null)
0019  #27.T7 [rcn, string] = QM_ASSIGN string("")
0020  SEND_VAL_EX #27.T7 [rcn, string] 3 ; op1(string)
0021  #29.T7 [] = COALESCE #16.CV3($systemId) [!null] -> #28.CV3($systemId) [null] 0023 ; op1(null)
0022  #30.T7 [rcn, string] = QM_ASSIGN string("")
0023  SEND_VAL_EX #30.T7 [rcn, string] 4 ; op1(string)
0024  DO_FCALL
      >enter Rowbot\DOM\DocumentType::__construct
       ;#33.CV2($publicId) NOVAL [undef]
       ;#34.CV3($systemId) NOVAL [undef]
0000   #35.CV0($document) [rc1, rcn, object] = RECV 1
0001   #36.CV1($name) [rc1, rcn, string] = RECV 2
0002   RECV_INIT 3 string("") #33.CV2($publicId) NOVAL [undef] -> #37.CV2($publicId) [rc1, rcn, string]
0003   ;RECV_INIT 4 string("") #34.CV3($systemId) NOVAL [undef] -> #38.CV3($systemId) [rc1, rcn, string]
0004   INIT_STATIC_METHOD_CALL 2 (parent) (exception) CONSTRUCTOR
       >init Rowbot\DOM\Node::__construct
0005   SEND_VAR_EX #35.CV0($document) [rc1, rcn, object] -> #39.CV0($document) NOVAL [rc1, rcn, object] 1 ; op1(object of class Rowbot\DOM\HTMLDocument)
0006   #40.T4 [!long] = FETCH_CLASS_CONSTANT (self) (exception) string("DOCUMENT_TYPE_NODE")
0007   SEND_VAL_EX #40.T4 [!long] 2 ; op1(int)
0008   DO_FCALL
       >enter Rowbot\DOM\Node::__construct
---- TRACE 641 TSSA stop (link to 77)
php: /home/trevor/.phpbrew/build/php-8.4.0alpha2/ext/opcache/jit/ir/ir.c:2810: _ir_RSTORE: Assertion `ctx->control' failed.
Aborted

These are the code locations mentioned in the trace.

https://github.com/TRowbotham/PHPDOM/blob/dev/src/Parser/Collection/ObjectStack.php#L55
https://github.com/TRowbotham/PHPDOM/blob/dev/src/Parser/HTML/InsertionMode/InitialInsertionMode.php#L54
https://github.com/TRowbotham/PHPDOM/blob/dev/src/DocumentType.php#L25
https://github.com/TRowbotham/PHPDOM/blob/dev/src/Node.php#L154

I hit this assertion when running vendor/bin/phpunit tests/html5lib/TreeBuilderTest.php

I will also note that this code is using the new property hooks feature, so it may be related to that.

Please let me know if I can provide any additional information.

@dstogov
Copy link
Member

dstogov commented Jul 29, 2024

Thanks!
I've reproduced the failure with a reduced test case.

<?php
class A {
   function test($context, $token) { 
       if ($token instanceof DoctypeToken) {
            $this->processDoctypeToken($context, $token);
        }
    }
    private function processDoctypeToken(TreeBuilderContext $context, DoctypeToken $token): void
    {
        $publicId = $token->publicIdentifier;
        $systemId = $token->systemIdentifier;
        $name = $token->name;

        if ($name !== 'html'
            || $publicId !== null
            || ($systemId !== null && $systemId !== 'about:legacy-compat')) {
        }

        $doctype = new DocumentType($context->document, $name ?? '', $publicId ?? '', $systemId ?? '');
    }
}
class Document {
}
final class TreeBuilderContext {
    public $document;
    public function __construct() {
        $this->document = new Document;
    }
}
abstract class Node {
    public const DOCUMENT_TYPE_NODE = 10;

    protected function __construct(Document $document, int $nodeType)
    {
    }
}
class DocumentType extends Node {
    public readonly string $name;
    public readonly string $publicId;
    public readonly string $systemId;

    public function __construct(
        Document $document,
        string $name,
        string $publicId = '',
        string $systemId = '') {
        parent::__construct($document, self::DOCUMENT_TYPE_NODE);
    }
}
class DoctypeToken {
    public $publicIdentifier;
    public $name;
    public $systemIdentifier;
}

$a = new A;
$doc = new TreeBuilderContext();
$t = new DoctypeToken();
$t->name = "html";
foreach ([$doc, $t] as $token) {
	$a->test($doc, $token);
}
?>

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

No branches or pull requests

3 participants