diff options
author | Nikita Popov <nikic@php.net> | 2015-05-22 22:17:40 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2015-05-23 10:51:33 +0200 |
commit | 7a88d16cf318c877d56c71756da95b57249c134a (patch) | |
tree | e54e2c2d3ef60570213b0f33f19aa1d94d7177f7 /Zend/zend_opcode.c | |
parent | 9325ada7253efb330e4fd79579d6e6fc0334d7b2 (diff) | |
download | php-git-7a88d16cf318c877d56c71756da95b57249c134a.tar.gz |
Use ZEND_JMP instead of ZEND_BRK/ZEND_CONT
Emit necessary FREEs during compilation, convert to JMP during
pass_two (we may not know target opline beforehand).
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r-- | Zend/zend_opcode.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 933c75a706..7365d6a518 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -666,6 +666,20 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num) } } +static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) { + int nest_levels = opline->op2.num; + int array_offset = opline->op1.num; + zend_brk_cont_element *jmp_to; + do { + jmp_to = &op_array->brk_cont_array[array_offset]; + if (nest_levels > 1) { + array_offset = jmp_to->parent; + } + } while (--nest_levels > 0); + + return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont; +} + static void zend_resolve_finally_calls(zend_op_array *op_array) { uint32_t i, j; @@ -681,22 +695,8 @@ static void zend_resolve_finally_calls(zend_op_array *op_array) break; case ZEND_BRK: case ZEND_CONT: - { - int nest_levels = opline->op2.num; - int array_offset = opline->op1.num; - zend_brk_cont_element *jmp_to; - - if (array_offset != -1) { - do { - jmp_to = &op_array->brk_cont_array[array_offset]; - if (nest_levels > 1) { - array_offset = jmp_to->parent; - } - } while (--nest_levels > 0); - zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont); - break; - } - } + zend_resolve_finally_call(op_array, i, zend_get_brk_cont_target(op_array, opline)); + break; case ZEND_GOTO: if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) != IS_LONG) { uint32_t num = opline->op2.constant; @@ -774,6 +774,16 @@ ZEND_API int pass_two(zend_op_array *op_array) case ZEND_DECLARE_INHERITED_CLASS_DELAYED: opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value); break; + case ZEND_BRK: + case ZEND_CONT: + { + uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline); + opline->opcode = ZEND_JMP; + opline->op1.opline_num = jmp_target; + opline->op2.num = 0; + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); + } + break; case ZEND_GOTO: if (Z_TYPE_P(RT_CONSTANT(op_array, opline->op2)) != IS_LONG) { zend_resolve_goto_label(op_array, opline, 1); |