Browse Source

optimizer: handle goto in convert_switch optimization

git-svn-id: svn://svn.lighttpd.net/xcache/trunk@834 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
3.0
Xuefer 10 years ago
parent
commit
07ca0eec2f
  1. 52
      optimizer.c

52
optimizer.c

@ -56,6 +56,7 @@ typedef xc_stack_t bbs_t;
static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
{
int i;
zend_bool preserve_brk_cont_array = 0;
if (op_array->brk_cont_array == NULL) {
return SUCCESS;
@ -64,11 +65,24 @@ static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
for (i = 0; i < op_array->last; i ++) {
zend_op *opline = &op_array->opcodes[i];
zend_brk_cont_element *jmp_to;
zend_bool can_convert = 1;
int array_offset, nest_levels, original_nest_levels;
if (opline->opcode != ZEND_BRK && opline->opcode != ZEND_CONT) {
switch (opline->opcode) {
case ZEND_BRK:
case ZEND_CONT:
break;
#ifdef ZEND_GOTO
case ZEND_GOTO:
preserve_brk_cont_array = 1;
continue;
#endif
default:
continue;
}
if (Z_OP_TYPE(opline->op2) != IS_CONST
|| Z_OP_CONSTANT(opline->op2).type != IS_LONG) {
return FAILURE;
@ -91,30 +105,40 @@ static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */
switch (brk_opline->opcode) {
case ZEND_SWITCH_FREE:
break;
case ZEND_FREE:
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
can_convert = 0;
preserve_brk_cont_array = 1;
}
break;
}
}
array_offset = jmp_to->parent;
} while (--nest_levels > 0);
/* rewrite to jmp */
if (opline->opcode == ZEND_BRK) {
Z_OP(opline->op1).opline_num = jmp_to->brk;
}
else {
Z_OP(opline->op1).opline_num = jmp_to->cont;
if (can_convert) {
/* rewrite to jmp */
switch (opline->opcode) {
case ZEND_BRK:
Z_OP(opline->op1).opline_num = jmp_to->brk;
break;
case ZEND_CONT:
Z_OP(opline->op1).opline_num = jmp_to->cont;
break;
}
Z_OP_TYPE(opline->op2) = IS_UNUSED;
opline->opcode = ZEND_JMP;
}
Z_OP_TYPE(opline->op2) = IS_UNUSED;
opline->opcode = ZEND_JMP;
}
if (op_array->brk_cont_array != NULL) {
efree(op_array->brk_cont_array);
op_array->brk_cont_array = NULL;
if (!preserve_brk_cont_array) {
if (op_array->brk_cont_array != NULL) {
efree(op_array->brk_cont_array);
op_array->brk_cont_array = NULL;
}
op_array->last_brk_cont = 0;
}
op_array->last_brk_cont = 0;
return SUCCESS;
}
/* }}} */

Loading…
Cancel
Save