summaryrefslogtreecommitdiff
path: root/Zend/zend_opcode.c
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2014-07-19 17:19:39 +0800
committerXinchen Hui <laruence@php.net>2014-07-19 17:19:39 +0800
commit1d2f232bd29dd29045c7389cf9d23b1ad2fd4db8 (patch)
treeb7edf8271a6dfa19003f0bc10f6b2b0feec685d6 /Zend/zend_opcode.c
parentcd95347cbc76e7c70207f3cab5a31c5fae03e4e3 (diff)
parent8ff00e6e85669ad0a5a47421fe639b6fb6f91669 (diff)
downloadphp-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.c100
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);