From 07ca0eec2f50e486c5e05ea8b3cfcfa6862cd7f0 Mon Sep 17 00:00:00 2001 From: Xuefer Date: Fri, 23 Mar 2012 17:17:10 +0000 Subject: [PATCH] optimizer: handle goto in convert_switch optimization git-svn-id: svn://svn.lighttpd.net/xcache/trunk@834 c26eb9a1-5813-0410-bd6c-c2e55f420ca7 --- optimizer.c | 52 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/optimizer.c b/optimizer.c index f19b335..b905c3c 100644 --- a/optimizer.c +++ b/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; } /* }}} */