summaryrefslogtreecommitdiff
path: root/Zend/zend_opcode.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-07-22 15:42:17 +0400
committerDmitry Stogov <dmitry@zend.com>2014-07-22 15:42:17 +0400
commitf2a2fcceceed5bb5851b459af9383d0da14a804b (patch)
tree6e9ac31a58214881ecd1380ba2b739b1dba17ce5 /Zend/zend_opcode.c
parent821b8bbb397a70151bdd039c072757e0f12fad19 (diff)
parentb39f98cf81cce1eae9f665a5c7f82c93e218a577 (diff)
downloadphp-git-f2a2fcceceed5bb5851b459af9383d0da14a804b.tar.gz
Merge branch 'master' into phpng
* master: fix nmake snap when ext name is different in target dll force atoll macro usage on windows Enable $ replacement in exif, ldap, pdo_pgsql and tidy See bug #67635 NEWS NEWS improve previous, add message during configure Fixed bug #67635 php links to systemd libraries without using pkg-config Improve fix for #66608 Fixed segfault with empty break New added opcodes don't need to be resloved Update NEWS Update NEWS Update NEWS Fixed bug #66827 Session raises E_NOTICE when session name variable is array implemented copy libs of core exts in phpize mode fix copy the ext dll into the prefix path in phpize mode fix default prefix in phpize mode fix file with zero size usage in phpize mode Conflicts: Zend/zend_opcode.c Zend/zend_vm_def.h Zend/zend_vm_execute.h ext/session/session.c
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r--Zend/zend_opcode.c104
1 files changed, 70 insertions, 34 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 2f0f0aeecd..8309599521 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -480,6 +480,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;
@@ -507,11 +550,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) {
@@ -574,32 +629,12 @@ 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;
+ zend_uint i, j;
zend_op *opline;
- for (i = 0; i < op_array->last; i++) {
+ for (i = 0, j = op_array->last; i < j; i++) {
opline = op_array->opcodes + i;
switch (opline->opcode) {
case ZEND_RETURN:
@@ -614,15 +649,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]);
- 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]) != IS_LONG) {
@@ -636,7 +672,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);