mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
parent
7fcbedd7df
commit
aa7465a435
3 changed files with 122 additions and 15 deletions
|
@ -1095,11 +1095,48 @@ static void zend_jit_allocate_registers(zend_jit_ctx *ctx, const zend_op_array *
|
|||
|
||||
/* Remove intervals used once */
|
||||
for (i = 0; i < ssa->vars_count; i++) {
|
||||
if (ra[i].ref &&
|
||||
(ra[i].flags & ZREG_LOAD) &&
|
||||
(ra[i].flags & ZREG_STORE) &&
|
||||
(ssa->vars[i].use_chain < 0 ||
|
||||
zend_ssa_next_use(ssa->ops, i, ssa->vars[i].use_chain) < 0)) {
|
||||
if (ra[i].ref) {
|
||||
if (!(ra[i].flags & (ZREG_LOAD|ZREG_STORE))) {
|
||||
uint32_t var_num = ssa->vars[i].var;
|
||||
uint32_t op_num = ssa->vars[i].definition;
|
||||
|
||||
/* Check if a tempoary variable may be freed by exception handler */
|
||||
if (op_array->last_live_range
|
||||
&& var_num >= op_array->last_var
|
||||
&& ssa->vars[i].definition >= 0
|
||||
&& ssa->ops[op_num].result_def == i) {
|
||||
const zend_live_range *range = op_array->live_range;
|
||||
int j;
|
||||
|
||||
op_num++;
|
||||
if (op_array->opcodes[op_num].opcode == ZEND_OP_DATA) {
|
||||
op_num++;
|
||||
}
|
||||
for (j = 0; j < op_array->last_live_range; range++, j++) {
|
||||
if (range->start > op_num) {
|
||||
/* further blocks will not be relevant... */
|
||||
break;
|
||||
} else if (op_num < range->end && var_num == (range->var & ~ZEND_LIVE_MASK)) {
|
||||
/* check if opcodes in range may throw */
|
||||
do {
|
||||
if (zend_may_throw(op_array->opcodes + op_num, ssa->ops + op_num, op_array, ssa)) {
|
||||
ra[i].flags |= ZREG_STORE;
|
||||
break;
|
||||
}
|
||||
op_num++;
|
||||
if (op_array->opcodes[op_num].opcode == ZEND_OP_DATA) {
|
||||
op_num++;
|
||||
}
|
||||
} while (op_num < range->end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ra[i].flags & ZREG_LOAD)
|
||||
&& (ra[i].flags & ZREG_STORE)
|
||||
&& (ssa->vars[i].use_chain < 0
|
||||
|| zend_ssa_next_use(ssa->ops, i, ssa->vars[i].use_chain) < 0)) {
|
||||
bool may_remove = 1;
|
||||
zend_ssa_phi *phi = ssa->vars[i].phi_use_chain;
|
||||
|
||||
|
@ -1117,6 +1154,7 @@ static void zend_jit_allocate_registers(zend_jit_ctx *ctx, const zend_op_array *
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (JIT_G(debug) & ZEND_JIT_DEBUG_REG_ALLOC) {
|
||||
fprintf(stderr, "Live Ranges \"%s\"\n", op_array->function_name ? ZSTR_VAL(op_array->function_name) : "[main]");
|
||||
|
|
|
@ -6174,6 +6174,56 @@ done:
|
|||
} else {
|
||||
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), type,
|
||||
(gen_handler || type == IS_UNKNOWN || !ra || !RA_HAS_REG(ssa_op->result_def)));
|
||||
|
||||
if (op_array->last_live_range
|
||||
&& opline->result.var > op_array->last_var
|
||||
&& STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var)) != type) {
|
||||
if (!gen_handler && type != IS_UNKNOWN && ra && RA_HAS_REG(ssa_op->result_def)) {
|
||||
uint32_t var_num = opline->result.var;
|
||||
uint32_t op_num = opline - op_array->opcodes;
|
||||
const zend_live_range *range = op_array->live_range;
|
||||
int j;
|
||||
|
||||
op_num += zend_jit_trace_op_len(opline);
|
||||
for (j = 0; j < op_array->last_live_range; range++, j++) {
|
||||
if (range->start > op_num) {
|
||||
/* further blocks will not be relevant... */
|
||||
break;
|
||||
} else if (op_num < range->end && var_num == (range->var & ~ZEND_LIVE_MASK)) {
|
||||
/* check if opcodes in range may throw */
|
||||
bool store_type = 0;
|
||||
const zend_ssa_op *next_ssa_op = ssa_op + zend_jit_trace_op_len(opline);
|
||||
const zend_jit_trace_rec *q = p + 1;
|
||||
|
||||
while (1) {
|
||||
if (q->op != ZEND_JIT_TRACE_VM) {
|
||||
store_type = 1;
|
||||
break;
|
||||
}
|
||||
op_num = q->opline - op_array->opcodes;
|
||||
if (op_num >= range->end || op_num < range->start) {
|
||||
break;
|
||||
}
|
||||
if (zend_may_throw(q->opline, next_ssa_op, op_array, ssa)) {
|
||||
store_type = 1;
|
||||
break;
|
||||
}
|
||||
next_ssa_op += zend_jit_trace_op_len(q->opline);
|
||||
q++;
|
||||
}
|
||||
if (store_type) {
|
||||
var_num = EX_VAR_TO_NUM(var_num);
|
||||
|
||||
if (!zend_jit_store_type(&ctx, var_num, type)) {
|
||||
return 0;
|
||||
}
|
||||
SET_STACK_TYPE(stack, var_num, type, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ssa->var_info[ssa_op->result_def].type & MAY_BE_INDIRECT) {
|
||||
RESET_STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var));
|
||||
}
|
||||
|
|
19
ext/opcache/tests/jit/reg_alloc_021.phpt
Normal file
19
ext/opcache/tests/jit/reg_alloc_021.phpt
Normal file
|
@ -0,0 +1,19 @@
|
|||
--TEST--
|
||||
Register Alloction 021: TMP variables captured by live_ranges have to be stored
|
||||
--INI--
|
||||
opcache.enable=1
|
||||
opcache.enable_cli=1
|
||||
opcache.file_update_protection=0
|
||||
opcache.jit_buffer_size=1M
|
||||
--FILE--
|
||||
<?php
|
||||
$a = 0;
|
||||
for($i = 5; $i >= 0; $i--) {
|
||||
$a = 1 + ++$a - 5 % $i;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %sreg_alloc_021.php:4
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %sreg_alloc_021.php on line 4
|
Loading…
Add table
Add a link
Reference in a new issue