Skip to content

Commit

Permalink
JIT x86: Fixed register clobbering in code produced for "$x[$y] %= $z".
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Sep 21, 2021
1 parent cebff25 commit f0f774a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 10 deletions.
31 changes: 21 additions & 10 deletions ext/opcache/jit/zend_jit_x86.dasc
Original file line number Diff line number Diff line change
Expand Up @@ -4939,6 +4939,9 @@ static int zend_jit_long_math_helper(dasm_State **Dst,

if (opcode == ZEND_MOD) {
result_reg = ZREG_RAX;
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
| mov aword T1, r0 // save
}
} else if (Z_MODE(res_addr) == IS_REG) {
if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR)
&& opline->op2_type != IS_CONST) {
Expand Down Expand Up @@ -5043,18 +5046,23 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
if (op2_lval == 0) {
| SET_EX_OPLINE opline, r0
| jmp ->mod_by_zero
} else if (op2_lval == -1) {
| xor Ra(result_reg), Ra(result_reg)
} else {
result_reg = ZREG_RDX;
| GET_ZVAL_LVAL ZREG_RAX, op1_addr
| GET_ZVAL_LVAL ZREG_RCX, op2_addr
|.if X64
| cqo
|.else
| cdq
|.endif
| idiv Ra(ZREG_RCX)
if (op2_lval == -1) {
| xor Ra(result_reg), Ra(result_reg)
} else {
| GET_ZVAL_LVAL ZREG_RAX, op1_addr
| GET_ZVAL_LVAL ZREG_RCX, op2_addr
|.if X64
| cqo
|.else
| cdq
|.endif
| idiv Ra(ZREG_RCX)
}
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
| mov r0, aword T1 // restore
}
}
} else {
if (!op2_range || (op2_range->min <= 0 && op2_range->max >= 0)) {
Expand Down Expand Up @@ -5105,6 +5113,9 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
} else if (Z_MODE(op2_addr) == IS_REG) {
| idiv Ra(Z_REG(op2_addr))
}
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
| mov r0, aword T1 // restore
}
}
} else if (same_ops) {
| GET_ZVAL_LVAL result_reg, op1_addr
Expand Down
36 changes: 36 additions & 0 deletions ext/opcache/tests/jit/mod_003.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
--TEST--
JIT MOD: 003
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.file_update_protection=0
opcache.jit_buffer_size=1M
opcache.protect_memory=1
opcache.jit=function
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
class Test {
public $prop = 0;
}
function test1($test) {
$test[0] %= 3;
return $test;
}
function test2($test) {
$test->prop %= 3;
return $test;
}
var_dump(test1([0]));
var_dump(test2(new Test));
?>
--EXPECT--
array(1) {
[0]=>
int(0)
}
object(Test)#1 (1) {
["prop"]=>
int(0)
}

0 comments on commit f0f774a

Please sign in to comment.