diff options
author | Xinchen Hui <laruence@php.net> | 2014-07-19 17:19:39 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@php.net> | 2014-07-19 17:19:39 +0800 |
commit | 1d2f232bd29dd29045c7389cf9d23b1ad2fd4db8 (patch) | |
tree | b7edf8271a6dfa19003f0bc10f6b2b0feec685d6 /Zend/zend_opcode.c | |
parent | cd95347cbc76e7c70207f3cab5a31c5fae03e4e3 (diff) | |
parent | 8ff00e6e85669ad0a5a47421fe639b6fb6f91669 (diff) | |
download | php-git-1d2f232bd29dd29045c7389cf9d23b1ad2fd4db8.tar.gz |
Merge branch 'PHP-5.5' into PHP-5.6
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r-- | Zend/zend_opcode.c | 100 |
1 files changed, 68 insertions, 32 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index a07544ff9a..bff314ef65 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -509,6 +509,49 @@ static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_nu } } +static void zend_adjust_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint start, zend_uint end TSRMLS_DC) +{ + int i; + zend_uint op_num = 0; + + for (i = 0; i < op_array->last_try_catch; i++) { + if (op_array->try_catch_array[i].finally_op > start + && op_array->try_catch_array[i].finally_end < end) { + op_num = op_array->try_catch_array[i].finally_op; + start = op_array->try_catch_array[i].finally_end; + } + } + + if (op_num) { + /* Must be ZEND_FAST_CALL */ + ZEND_ASSERT(op_array->opcodes[op_num - 2].opcode == ZEND_FAST_CALL); + op_array->opcodes[op_num - 2].extended_value = ZEND_FAST_CALL_FROM_FINALLY; + op_array->opcodes[op_num - 2].op2.opline_num = fast_call; + } +} + +static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint op_num TSRMLS_DC) +{ + int i; + zend_uint finally_op_num = 0; + + for (i = 0; i < op_array->last_try_catch; i++) { + if (op_num >= op_array->try_catch_array[i].finally_op + && op_num < op_array->try_catch_array[i].finally_end) { + finally_op_num = op_array->try_catch_array[i].finally_op; + } + } + + if (finally_op_num) { + /* Must be ZEND_FAST_CALL */ + ZEND_ASSERT(op_array->opcodes[finally_op_num - 2].opcode == ZEND_FAST_CALL); + if (op_array->opcodes[fast_call].extended_value == 0) { + op_array->opcodes[fast_call].extended_value = ZEND_FAST_CALL_FROM_FINALLY; + op_array->opcodes[fast_call].op2.opline_num = finally_op_num - 2; + } + } +} + static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) { zend_uint start_op; @@ -536,11 +579,23 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, opline->opcode = ZEND_FAST_CALL; SET_UNUSED(opline->op1); SET_UNUSED(opline->op2); - opline->op1.opline_num = op_array->try_catch_array[i].finally_op; + zend_adjust_fast_call(op_array, start_op, + op_array->try_catch_array[i].finally_op, + op_array->try_catch_array[i].finally_end TSRMLS_CC); if (op_array->try_catch_array[i].catch_op) { - opline->extended_value = ZEND_FAST_CALL_FOR_CATCH; + opline->extended_value = ZEND_FAST_CALL_FROM_CATCH; opline->op2.opline_num = op_array->try_catch_array[i].catch_op; + opline->op1.opline_num = get_next_op_number(op_array); + /* generate a FAST_CALL to hole CALL_FROM_FINALLY */ + opline = get_next_op(op_array TSRMLS_CC); + opline->opcode = ZEND_FAST_CALL; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + zend_resolve_fast_call(op_array, start_op + 1, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC); + } else { + zend_resolve_fast_call(op_array, start_op, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC); } + opline->op1.opline_num = op_array->try_catch_array[i].finally_op; /* generate a sequence of FAST_CALL to upward finally block */ while (i > 0) { @@ -603,26 +658,6 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num T } } -static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint op_num TSRMLS_DC) -{ - int i; - zend_uint finally_op_num = 0; - - for (i = 0; i < op_array->last_try_catch; i++) { - if (op_array->try_catch_array[i].finally_op > op_num) { - break; - } - if (op_num < op_array->try_catch_array[i].finally_end) { - finally_op_num = op_array->try_catch_array[i].finally_op; - } - } - - if (finally_op_num) { - op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FOR_FINALLY; - op_array->opcodes[op_num].op2.opline_num = finally_op_num - 2; /* it must be ZEND_FAST_CALL */ - } -} - static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) { zend_uint i, j; @@ -643,15 +678,16 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) zend_brk_cont_element *jmp_to; nest_levels = Z_LVAL(op_array->literals[opline->op2.constant].constant); - array_offset = opline->op1.opline_num; - 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 TSRMLS_CC); - break; + if ((array_offset = opline->op1.opline_num) != -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 TSRMLS_CC); + break; + } } case ZEND_GOTO: if (Z_TYPE(op_array->literals[opline->op2.constant].constant) != IS_LONG) { @@ -665,7 +701,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC); break; case ZEND_FAST_CALL: - zend_resolve_fast_call(op_array, i TSRMLS_CC); + zend_resolve_fast_call(op_array, i, i TSRMLS_CC); break; case ZEND_FAST_RET: zend_resolve_finally_ret(op_array, i TSRMLS_CC); |