Bug #81249 [Com]: Intermittent property assignment failure with JIT enabled

From: Date: Mon, 19 Jul 2021 06:27:07 +0000
Subject: Bug #81249 [Com]: Intermittent property assignment failure with JIT enabled
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-235154@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=81249&edit=1

 ID:                 81249
 Comment by:         hao dot sun at arm dot com
 Reported by:        smokey101stair at gmail dot com
 Summary:            Intermittent property assignment failure with JIT
                     enabled
 Status:             Verified
 Type:               Bug
 Package:            JIT
 Operating System:   Ubuntu 20.04
 PHP Version:        8.0.8
 Assigned To:        dmitry
 Block user comment: N
 Private report:     N

 New Comment:

Based on my local debugging, I suspected function zend_jit_may_skip_comparison().

Code is not generated as expected for the hot side trace for statement: "if ($byte === 0x8E ||
$byte === 0x8F || ($byte >= 0xA1 && $byte <= 0xFE)) {"
Here is trace #5: (Note several "echo" statements are inserted in my local debugging). For
"$byte === 0x8E || $byte === 0x8F", there are two IS_IDENTICAL opcodes.

     TRACE 3 exit 1 EucJpDecoder::handle() /home/haosun01/php/7.php:91
---- TRACE 5 start (side trace 3/1) EucJpDecoder::handle() /home/haosun01/php/7.php:91
========3333333 143
===== 44444444 set lead here: 143 : 143
0086 T7 = ROPE_INIT 3 string("========3333333 ")
0087 T7 = ROPE_ADD 1 T7 CV1($byte) ; op2(int)
0088 T6 = ROPE_END 2 T7 string("
")
0089 ECHO T6 ; op1(string)
0090 T6 = IS_IDENTICAL CV1($byte) int(142) ; op1(int)
0091 ;JMPNZ T6 0098
0092 T6 = IS_IDENTICAL CV1($byte) int(143) ; op1(int)
0093 ;JMPNZ T6 0098
0098 ASSIGN_OBJ THIS string("lead") ; op3(int)
0099 ;OP_DATA CV1($byte)
0100 T7 = ROPE_INIT 5 string("===== 44444444 set lead here: ")
0101 T7 = ROPE_ADD 1 T7 CV1($byte) ; op2(int)
0102 T7 = ROPE_ADD 2 T7 string(" : ")
0103 T6 = FETCH_OBJ_R THIS string("lead")
0104 T7 = ROPE_ADD 3 T7 T6 ; op2(int)
0105 T6 = ROPE_END 4 T7 string("
")
0106 ECHO T6 ; op1(string)
0107 RETURN int(-1)
---- TRACE 5 stop (return)


However, in the compiled code, I found that only the code for "$byte === 0x8E" is
generated. Here is part of the code. See "cmp x15, #0x8e".

.L1:
    ffffbb9c8250:       movz x15, #0x51c0
    ffffbb9c8254:       movk x15, #0xabb6, lsl #16
    ffffbb9c8258:       movk x15, #0xaaaa, lsl #32
    ffffbb9c825c:       ldr x8, [x15]
    ffffbb9c8260:       cbnz x8, #JIT$$exception_handler
    ffffbb9c8264:       ldr x15, [x27, #0x60]
    ffffbb9c8268:       cmp x15, #0x8e
    ffffbb9c826c:       b.eq #jit$$trace_exit_0
    ffffbb9c8270:       b.ne #jit$$trace_exit_1
    ffffbb9c8274:       ldr x0, [x27, #0x20]
    ffffbb9c8278:       ldrb w16, [x0, #0x30]
    ffffbb9c827c:       cbz w16, #jit$$trace_exit_2
    ffffbb9c8280:       add x0, x0, #0x28
    ffffbb9c8284:       add x1, x27, #0x60
    ffffbb9c8288:       adrp x8, #0xffffb4298000
    ffffbb9c828c:       add x8, x8, #0xa70
    ffffbb9c8290:       str x8, [x27]
    ffffbb9c8294:       bl #JIT$$assign_tmp
    ffffbb9c8298:       movz x15, #0x51c0
    ffffbb9c829c:       movk x15, #0xabb6, lsl #16
    ffffbb9c82a0:       movk x15, #0xaaaa, lsl #32
    ffffbb9c82a4:       ldr x8, [x15]
    ffffbb9c82a8:       cbnz x8, #JIT$$exception_handler
    ffffbb9c82ac:       movz x15, #0x160
    ffffbb9c82b0:       add x28, x28, x15


That is because "skip_comparison" is set as true for the second ZEND_IS_IDENTICAL, i.e.
JIT is bypassed.
In details, in file zend_jit_trace.c, these code
(https://github.com/php/php-src/blob/master/ext/opcache/jit/zend_jit_trace.c#L4762-L4812) is used to
generate the JIT code for ZEND_IS_IDENTICAL. However, I found that variable
"skip_comparison" is set as false for "$byte === 0x8E", but is set as true for
"$byte === 0x8F".
I further looked at function zend_jit_may_skip_comparison(). I noticed that for $byte === 0x8F, this
function returns "1" at https://github.com/php/php-src/blob/master/ext/opcache/jit/zend_jit_trace.c#L3568



In one word, I guess the root cause of this bug lies in how to determine "skip_comparison"
for the case of two consecutive "ZEND_IS_IDENTICAL".
As I tried, if we always set variable "skip_comparison" as false, this bug can be gone.


Previous Comments:
------------------------------------------------------------------------
[2021-07-19 00:30:59] hao dot sun at arm dot com

FYI.

1. This bug occurred for master branch as well, for both JIT/x86 and JIT/arm64.
2. In my test, the test case can be further downsized, that is, Lines 85 to 87 can be removed as
well, i.e. https://gist.github.com/TRowbotham/4dc7c8dc1714edab69019e0d71c17c02#file-jit1-php-L85-L87
3. I suspect this bug is due to "hot side exit".
1) -d opcache.jit_hot_side_exit=0, this bug is gone.
2) -d opcache.jit_hot_side_exit=N, the smaller the number we assigned, the earlier this bug showed
up.

------------------------------------------------------------------------
[2021-07-12 03:46:12] smokey101stair at gmail dot com

Description:
------------
PHP 8.0.8 (cli) (built: Jul  4 2021 21:22:34) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.8, Copyright (c), by Zend Technologies

PHP was compiled using PHPBrew, if that makes a difference.

opcache.jit=1255
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.jit_buffer_size=256M
zend.assertions=1

The test script decodes EUC-JP text to Unicode Code Points. I tried to reduce the script as much as
possible, but it was very temperamental when removing if statements.

When processing the first byte, 8F, the assignment at https://gist.github.com/TRowbotham/4dc7c8dc1714edab69019e0d71c17c02#file-jit1-php-L90
fails intermittently. This leaves $this->lead set to its initial value of 0, which eventually
leads to the script returning an error instead of a code point.

The script is expected to transform the EUC-JP encoded bytes to the Unicode U+2D8 code point.

Test script:
---------------
https://gist.github.com/TRowbotham/4dc7c8dc1714edab69019e0d71c17c02



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=81249&edit=1


Thread (5 messages)

« previous php.bugs (#235154) next »