mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
Use op_array->T_liveliness to free incomplete ropes and restore error_reporting level on exception
This commit is contained in:
parent
80c1d0d779
commit
8d1f88fe91
@ -6265,10 +6265,8 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
|
||||
{
|
||||
zend_ast *expr_ast = ast->child[0];
|
||||
znode silence_node;
|
||||
uint32_t begin_opline_num, end_opline_num;
|
||||
zend_brk_cont_element *brk_cont_element;
|
||||
|
||||
begin_opline_num = get_next_op_number(CG(active_op_array));
|
||||
zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
|
||||
|
||||
if (expr_ast->kind == ZEND_AST_VAR) {
|
||||
@ -6279,15 +6277,7 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
|
||||
zend_compile_expr(result, expr_ast);
|
||||
}
|
||||
|
||||
end_opline_num = get_next_op_number(CG(active_op_array));
|
||||
zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
|
||||
|
||||
/* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
|
||||
* EG(error_reporting) value on exception */
|
||||
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
|
||||
brk_cont_element->start = begin_opline_num;
|
||||
brk_cont_element->cont = brk_cont_element->brk = end_opline_num;
|
||||
brk_cont_element->parent = -1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -6615,10 +6605,6 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
|
||||
GET_NODE(result, opline->result);
|
||||
} else {
|
||||
uint32_t var;
|
||||
zend_brk_cont_element *info = get_next_brk_cont_element(CG(active_op_array));
|
||||
info->start = rope_init_lineno;
|
||||
info->parent = CG(context).current_brk_cont;
|
||||
info->cont = info->brk = opline - CG(active_op_array)->opcodes;
|
||||
|
||||
init_opline->extended_value = j;
|
||||
opline->opcode = ZEND_ROPE_END;
|
||||
|
@ -328,6 +328,9 @@ typedef struct _zend_internal_function_info {
|
||||
zend_bool _is_variadic;
|
||||
} zend_internal_function_info;
|
||||
|
||||
#define ZEND_LIVE_ROPE (1 << 0)
|
||||
#define ZEND_LIVE_SILENCE (1 << 1)
|
||||
|
||||
struct _zend_op_array {
|
||||
/* Common elements */
|
||||
zend_uchar type;
|
||||
|
@ -2390,7 +2390,33 @@ static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data
|
||||
uint32_t *off = EX(func)->op_array.T_liveliness + EX(func)->op_array.T_liveliness[op_num];
|
||||
uint32_t *until = EX(func)->op_array.T_liveliness + EX(func)->op_array.T_liveliness[op_num + 1];
|
||||
while (off < until) {
|
||||
zval_ptr_dtor_nogc(ZEND_CALL_VAR_NUM(execute_data, *(off++)));
|
||||
uint32_t var = *(off++);
|
||||
|
||||
if (var & ZEND_LIVE_ROPE) {
|
||||
/* free incomplete rope */
|
||||
zend_string **rope = (zend_string **) EX_VAR(var & ~ZEND_LIVE_ROPE);
|
||||
zend_op *last = EX(func)->op_array.opcodes + op_num;
|
||||
while (last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT) {
|
||||
ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
|
||||
last--;
|
||||
}
|
||||
if (last->opcode == ZEND_ROPE_INIT) {
|
||||
zend_string_release(*rope);
|
||||
} else {
|
||||
int j = last->extended_value;
|
||||
do {
|
||||
zend_string_release(rope[j]);
|
||||
} while (j--);
|
||||
}
|
||||
} else if (var & ZEND_LIVE_SILENCE) {
|
||||
/* restore previous error_reporting value */
|
||||
var = var & ~ZEND_LIVE_SILENCE;
|
||||
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(var)) != 0) {
|
||||
EG(error_reporting) = Z_LVAL_P(EX_VAR(var));
|
||||
}
|
||||
} else {
|
||||
zval_ptr_dtor_nogc(EX_VAR(var));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2527,26 +2553,6 @@ static zend_always_inline void i_cleanup_unfinished_execution(zend_execute_data
|
||||
zend_hash_iterator_del(Z_FE_ITER_P(var));
|
||||
}
|
||||
zval_ptr_dtor_nogc(var);
|
||||
} else if (brk_opline->opcode == ZEND_ROPE_END) {
|
||||
zend_string **rope = (zend_string **) EX_VAR(brk_opline->op1.var);
|
||||
zend_op *last = EX(func)->op_array.opcodes + op_num;
|
||||
while (last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT) {
|
||||
ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
|
||||
last--;
|
||||
}
|
||||
if (last->opcode == ZEND_ROPE_INIT) {
|
||||
zend_string_release(*rope);
|
||||
} else {
|
||||
int j = last->extended_value;
|
||||
do {
|
||||
zend_string_release(rope[j]);
|
||||
} while (j--);
|
||||
}
|
||||
} else if (brk_opline->opcode == ZEND_END_SILENCE) {
|
||||
/* restore previous error_reporting value */
|
||||
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
|
||||
EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -855,7 +855,7 @@ typedef struct _var_live_info {
|
||||
|
||||
typedef struct _op_var_info {
|
||||
struct _op_var_info *next;
|
||||
uint32_t T;
|
||||
uint32_t var;
|
||||
} op_var_info;
|
||||
|
||||
ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
@ -876,7 +876,7 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
|
||||
for (i = 0; i <= op_array->last; i++) {
|
||||
opTs[i] = &opTsTop[i];
|
||||
opTs[i]->T = -1;
|
||||
opTs[i]->var = -1;
|
||||
opTs[i]->next = NULL;
|
||||
}
|
||||
|
||||
@ -894,7 +894,7 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
}
|
||||
if (!~T->start
|
||||
&& cur_op->opcode != ZEND_CASE /* exception for opcache, is anyway bool */
|
||||
&& cur_op->opcode != ZEND_ROPE_INIT && cur_op->opcode != ZEND_ROPE_ADD
|
||||
&& cur_op->opcode != ZEND_ROPE_ADD /* reuses TMP created in ROPE_INIT */
|
||||
&& cur_op->opcode != ZEND_FAST_CALL && cur_op->opcode != ZEND_FAST_RET
|
||||
&& cur_op->opcode != ZEND_FETCH_CLASS && cur_op->opcode != ZEND_DECLARE_CLASS
|
||||
&& cur_op->opcode != ZEND_DECLARE_INHERITED_CLASS && cur_op->opcode != ZEND_DECLARE_INHERITED_CLASS_DELAYED
|
||||
@ -909,7 +909,7 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
}
|
||||
if ((cur_op->op1_type & (IS_VAR | IS_TMP_VAR))
|
||||
&& cur_op->opcode != ZEND_FE_FREE
|
||||
&& cur_op->opcode != ZEND_ROPE_ADD && cur_op->opcode != ZEND_ROPE_END) {
|
||||
&& cur_op->opcode != ZEND_ROPE_ADD) {
|
||||
var_live_info *T = Ts[cur_op->op1.var];
|
||||
if (~T->start) {
|
||||
T->end = cur_op - op_array->opcodes;
|
||||
@ -943,11 +943,16 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
for (j = T->start + 1; j < T->end; j++) {
|
||||
if (op_array->opcodes[j].opcode != ZEND_THROW) {
|
||||
op_var_info *opT = opTs[j];
|
||||
if (~opT->T) {
|
||||
if (~opT->var) {
|
||||
opT = opTs[j] = opT->next = zend_arena_alloc(&CG(arena), sizeof(op_var_info));
|
||||
opT->next = NULL;
|
||||
}
|
||||
opT->T = i;
|
||||
opT->var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + i);;
|
||||
if (op_array->opcodes[T->end].opcode == ZEND_ROPE_END) {
|
||||
opT->var |= ZEND_LIVE_ROPE;
|
||||
} else if (op_array->opcodes[T->end].opcode == ZEND_END_SILENCE) {
|
||||
opT->var |= ZEND_LIVE_SILENCE;
|
||||
}
|
||||
op_live_total++;
|
||||
}
|
||||
}
|
||||
@ -964,11 +969,11 @@ ZEND_API uint32_t *generate_var_liveliness_info(zend_op_array *op_array)
|
||||
for (i = 0; i < op_array->last; i++) {
|
||||
op_var_info *opT = &opTsTop[i];
|
||||
info[i] = info_off;
|
||||
if (!~opT->T) {
|
||||
if (!~opT->var) {
|
||||
opT = NULL;
|
||||
}
|
||||
while (opT) {
|
||||
info[info_off++] = op_array->last_var + opT->T;
|
||||
info[info_off++] = opT->var;
|
||||
opT = opT->next;
|
||||
}
|
||||
}
|
||||
|
@ -207,17 +207,13 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
|
||||
for (i = 0; i< op_array->last_brk_cont; i++) {
|
||||
if (op_array->brk_cont_array[i].start >= 0 &&
|
||||
(op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE)) {
|
||||
int parent = op_array->brk_cont_array[i].parent;
|
||||
|
||||
while (parent >= 0 &&
|
||||
op_array->brk_cont_array[parent].start < 0 &&
|
||||
(op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FE_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode != ZEND_ROPE_END ||
|
||||
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_END_SILENCE)) {
|
||||
op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FE_FREE)) {
|
||||
parent = op_array->brk_cont_array[parent].parent;
|
||||
}
|
||||
op_array->brk_cont_array[i].parent = parent;
|
||||
@ -232,9 +228,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
|
||||
for (i = 0; i< op_array->last_brk_cont; i++) {
|
||||
if (op_array->brk_cont_array[i].start >= 0 &&
|
||||
(op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
|
||||
op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE)) {
|
||||
if (i != j) {
|
||||
op_array->brk_cont_array[j] = op_array->brk_cont_array[i];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user