diff options
-rw-r--r-- | Zend/zend_compile.c | 12 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 10 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 120 | ||||
-rw-r--r-- | Zend/zend_vm_gen.php | 3 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 2 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.h | 1 | ||||
-rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 4 | ||||
-rw-r--r-- | ext/opcache/Optimizer/dfa_pass.c | 6 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_cfg.c | 8 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_dump.c | 20 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 26 | ||||
-rw-r--r-- | ext/opcache/zend_file_cache.c | 10 | ||||
-rw-r--r-- | ext/opcache/zend_persist.c | 5 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_opcode.c | 8 | ||||
-rw-r--r-- | sapi/phpdbg/phpdbg_utils.c | 12 | ||||
-rw-r--r-- | sapi/phpdbg/tests/exceptions_003.phpt | 2 | ||||
-rw-r--r-- | sapi/phpdbg/tests/stepping_001.phpt | 2 |
19 files changed, 154 insertions, 105 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index e8a16c4ef0..0b4941e1f4 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5201,15 +5201,17 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); } - opline->op2_type = IS_CV; - opline->op2.var = lookup_cv(CG(active_op_array), var_name); + opline->result_type = IS_CV; + opline->result.var = lookup_cv(CG(active_op_array), var_name); - opline->result.num = is_last_catch && is_last_class; + if (is_last_catch && is_last_class) { + opline->extended_value = ZEND_LAST_CATCH; + } if (!is_last_class) { jmp_multicatch[j] = zend_emit_jump(0); opline = &CG(active_op_array)->opcodes[opnum_catch]; - opline->extended_value = get_next_op_number(CG(active_op_array)); + opline->op2.opline_num = get_next_op_number(CG(active_op_array)); } } @@ -5227,7 +5229,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ opline = &CG(active_op_array)->opcodes[opnum_catch]; if (!is_last_catch) { - opline->extended_value = get_next_op_number(CG(active_op_array)); + opline->op2.opline_num = get_next_op_number(CG(active_op_array)); } } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 228111e29e..d787a92a7f 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -877,6 +877,8 @@ void zend_assert_valid_class_name(const zend_string *const_name); #define ZEND_FETCH_ARG_MASK 0x0fffffff +#define ZEND_LAST_CATCH 0x00000001 + #define ZEND_FREE_ON_RETURN (1<<0) #define ZEND_SEND_BY_VAL 0 diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index a0301a9add..41b40a2663 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -657,12 +657,16 @@ ZEND_API int pass_two(zend_op_array *op_array) } case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: - case ZEND_CATCH: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: /* absolute index to relative offset */ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); + } + break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index a7fa49c433..979b4f6c06 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4082,7 +4082,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) HANDLE_EXCEPTION(); } -ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR) +ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, JMP_ADDR, LAST_CATCH) { USE_OPLINE zend_class_entry *ce, *catch_ce; @@ -4093,7 +4093,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR) /* Check whether an exception has been thrown, if not, jump over code */ zend_exception_restore(); if (EG(exception) == NULL) { - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2)); ZEND_VM_CONTINUE(); } catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))); @@ -4112,17 +4112,17 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR) if (ce != catch_ce) { if (!catch_ce || !instanceof_function(ce, catch_ce)) { - if (opline->result.num) { + if (opline->extended_value == ZEND_LAST_CATCH) { zend_rethrow_exception(execute_data); HANDLE_EXCEPTION(); } - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2)); ZEND_VM_CONTINUE(); } } exception = EG(exception); - ex = EX_VAR(opline->op2.var); + ex = EX_VAR(opline->result.var); if (UNEXPECTED(Z_ISREF_P(ex))) { ex = Z_REFVAL_P(ex); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1277156fdf..a26a4b6e5a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2904,6 +2904,61 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_ HANDLE_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_class_entry *ce, *catch_ce; + zend_object *exception; + zval *ex; + + SAVE_OPLINE(); + /* Check whether an exception has been thrown, if not, jump over code */ + zend_exception_restore(); + if (EG(exception) == NULL) { + ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2)); + ZEND_VM_CONTINUE(); + } + catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))); + if (UNEXPECTED(catch_ce == NULL)) { + catch_ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), RT_CONSTANT(opline, opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD); + + CACHE_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)), catch_ce); + } + ce = EG(exception)->ce; + +#ifdef HAVE_DTRACE + if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { + DTRACE_EXCEPTION_CAUGHT((char *)ce->name); + } +#endif /* HAVE_DTRACE */ + + if (ce != catch_ce) { + if (!catch_ce || !instanceof_function(ce, catch_ce)) { + if (opline->extended_value == ZEND_LAST_CATCH) { + zend_rethrow_exception(execute_data); + HANDLE_EXCEPTION(); + } + ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2)); + ZEND_VM_CONTINUE(); + } + } + + exception = EG(exception); + ex = EX_VAR(opline->result.var); + if (UNEXPECTED(Z_ISREF_P(ex))) { + ex = Z_REFVAL_P(ex); + } + zval_ptr_dtor(ex); + ZVAL_OBJ(ex, EG(exception)); + if (UNEXPECTED(EG(exception) != exception)) { + GC_ADDREF(EG(exception)); + HANDLE_EXCEPTION(); + } else { + EG(exception) = NULL; + ZEND_VM_NEXT_OPCODE(); + } +} + static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10768,61 +10823,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_H ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_class_entry *ce, *catch_ce; - zend_object *exception; - zval *ex; - - SAVE_OPLINE(); - /* Check whether an exception has been thrown, if not, jump over code */ - zend_exception_restore(); - if (EG(exception) == NULL) { - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } - catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1))); - if (UNEXPECTED(catch_ce == NULL)) { - catch_ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), RT_CONSTANT(opline, opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD); - - CACHE_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(opline, opline->op1)), catch_ce); - } - ce = EG(exception)->ce; - -#ifdef HAVE_DTRACE - if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) { - DTRACE_EXCEPTION_CAUGHT((char *)ce->name); - } -#endif /* HAVE_DTRACE */ - - if (ce != catch_ce) { - if (!catch_ce || !instanceof_function(ce, catch_ce)) { - if (opline->result.num) { - zend_rethrow_exception(execute_data); - HANDLE_EXCEPTION(); - } - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } - } - - exception = EG(exception); - ex = EX_VAR(opline->op2.var); - if (UNEXPECTED(Z_ISREF_P(ex))) { - ex = Z_REFVAL_P(ex); - } - zval_ptr_dtor(ex); - ZVAL_OBJ(ex, EG(exception)); - if (UNEXPECTED(EG(exception) != exception)) { - GC_ADDREF(EG(exception)); - HANDLE_EXCEPTION(); - } else { - EG(exception) = NULL; - ZEND_VM_NEXT_OPCODE(); - } -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -54885,7 +54885,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_EXT_NOP_SPEC_LABEL, (void*)&&ZEND_TICKS_SPEC_LABEL, (void*)&&ZEND_SEND_VAR_NO_REF_SPEC_VAR_LABEL, - (void*)&&ZEND_CATCH_SPEC_CONST_CV_LABEL, + (void*)&&ZEND_CATCH_SPEC_CONST_LABEL, (void*)&&ZEND_THROW_SPEC_CONST_LABEL, (void*)&&ZEND_THROW_SPEC_TMP_LABEL, (void*)&&ZEND_THROW_SPEC_VAR_LABEL, @@ -57012,6 +57012,9 @@ ZEND_API void execute_ex(zend_execute_data *ex) HYBRID_CASE(ZEND_THROW_SPEC_CONST): ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_CATCH_SPEC_CONST): + ZEND_CATCH_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_SEND_VAL_SPEC_CONST): ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); @@ -57525,9 +57528,6 @@ ZEND_API void execute_ex(zend_execute_data *ex) HYBRID_CASE(ZEND_INIT_USER_CALL_SPEC_CONST_CV): ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_CATCH_SPEC_CONST_CV): - ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV): ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); @@ -62770,7 +62770,7 @@ void zend_init_opcodes_handlers(void) ZEND_EXT_NOP_SPEC_HANDLER, ZEND_TICKS_SPEC_HANDLER, ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, - ZEND_CATCH_SPEC_CONST_CV_HANDLER, + ZEND_CATCH_SPEC_CONST_HANDLER, ZEND_THROW_SPEC_CONST_HANDLER, ZEND_THROW_SPEC_TMP_HANDLER, ZEND_THROW_SPEC_VAR_HANDLER, diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 75afa99624..2c392b8760 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -78,7 +78,7 @@ $vm_op_flags = array( "ZEND_VM_EXT_REF" => 1<<20, "ZEND_VM_EXT_MASK" => 0x0f000000, "ZEND_VM_EXT_NUM" => 0x01000000, - // unused 0x2000000 + "ZEND_VM_EXT_LAST_CATCH" => 0x02000000, "ZEND_VM_EXT_JMP_ADDR" => 0x03000000, "ZEND_VM_EXT_DIM_OBJ" => 0x04000000, // unused 0x5000000 @@ -119,6 +119,7 @@ $vm_op_decode = array( $vm_ext_decode = array( "NUM" => ZEND_VM_EXT_NUM, + "LAST_CATCH" => ZEND_VM_EXT_LAST_CATCH, "JMP_ADDR" => ZEND_VM_EXT_JMP_ADDR, "DIM_OBJ" => ZEND_VM_EXT_DIM_OBJ, "VAR_FETCH" => ZEND_VM_EXT_VAR_FETCH, diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 876dfef315..b01d7395d3 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -331,7 +331,7 @@ static uint32_t zend_vm_opcodes_flags[199] = { 0x00000000, 0x01000000, 0x00001001, - 0x03000103, + 0x02002003, 0x00000003, 0x00000771, 0x00000057, diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index a1191cac29..fc0cba498f 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -55,6 +55,7 @@ #define ZEND_VM_EXT_REF 0x00100000 #define ZEND_VM_EXT_MASK 0x0f000000 #define ZEND_VM_EXT_NUM 0x01000000 +#define ZEND_VM_EXT_LAST_CATCH 0x02000000 #define ZEND_VM_EXT_JMP_ADDR 0x03000000 #define ZEND_VM_EXT_DIM_OBJ 0x04000000 #define ZEND_VM_EXT_TYPE 0x07000000 diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 6568bdc1b3..65007a9455 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -965,8 +965,8 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start); break; case ZEND_CATCH: - if (!opline->result.var) { - opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[0]].start); + if (opline->extended_value != ZEND_LAST_CATCH) { + ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start); } break; case ZEND_DECLARE_ANON_CLASS: diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index f24d407eeb..13aec486f6 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -552,9 +552,9 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa } break; case ZEND_CATCH: - if (!opline->result.num) { - if (ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) == old->start) { - opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, dst->start); + if (opline->extended_value != ZEND_LAST_CATCH) { + if (ZEND_OP2_JMP_ADDR(opline) == op_array->opcodes + old->start) { + ZEND_SET_OP_JMP_ADDR(opline, opline->op2, op_array->opcodes + dst->start); } } break; diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index 77371c97c2..a2d021516d 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -385,8 +385,8 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b BB_START(i + 1); break; case ZEND_CATCH: - if (!opline->result.num) { - BB_START(ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); + if (opline->extended_value != ZEND_LAST_CATCH) { + BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes); } BB_START(i + 1); break; @@ -546,9 +546,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b block->successors[1] = j + 1; break; case ZEND_CATCH: - if (!opline->result.num) { + if (opline->extended_value != ZEND_LAST_CATCH) { block->successors_count = 2; - block->successors[0] = block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]; + block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]; block->successors[1] = j + 1; } else { block->successors_count = 1; diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 8f874d8bdb..a2bba55178 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -681,10 +681,12 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * } else { uint32_t op2_flags = ZEND_VM_OP2_FLAGS(flags); if (ZEND_VM_OP_JMP_ADDR == (op2_flags & ZEND_VM_OP_MASK)) { - if (b) { - fprintf(stderr, " BB%d", b->successors[n++]); - } else { - fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes)); + if (opline->opcode != ZEND_CATCH || opline->extended_value != ZEND_LAST_CATCH) { + if (b) { + fprintf(stderr, " BB%d", b->successors[n++]); + } else { + fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes)); + } } } else { zend_dump_unused_op(opline, opline->op2, op2_flags); @@ -692,12 +694,10 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * } if (ZEND_VM_EXT_JMP_ADDR == (flags & ZEND_VM_EXT_MASK)) { - if (opline->opcode != ZEND_CATCH || !opline->result.num) { - if (b) { - fprintf(stderr, " BB%d", b->successors[n++]); - } else { - fprintf(stderr, " L%u", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); - } + if (b) { + fprintf(stderr, " BB%d", b->successors[n++]); + } else { + fprintf(stderr, " L%u", (uint32_t)ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); } } if (opline->result_type == IS_CONST) { diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 1bf05a50a9..a7d463030f 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -757,17 +757,17 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z case ZEND_ASSERT_CHECK: ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline)); break; - case ZEND_CATCH: - if (!opline->result.num) { - new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); - } - break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline)); + } + break; case ZEND_SWITCH_LONG: case ZEND_SWITCH_STRING: { @@ -803,11 +803,15 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_ case ZEND_ASSERT_CHECK: ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]); break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]); + } + break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: - case ZEND_CATCH: opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) - shiftlist[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]); break; case ZEND_SWITCH_LONG: @@ -1167,6 +1171,11 @@ static void zend_redo_pass_two(zend_op_array *op_array) case ZEND_ASSERT_CHECK: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; + } + break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: @@ -1248,6 +1257,11 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa) case ZEND_ASSERT_CHECK: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; + } + break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index c11bff3868..db926a5172 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -446,6 +446,11 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra case ZEND_ASSERT_CHECK: SERIALIZE_PTR(opline->op2.jmp_addr); break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + SERIALIZE_PTR(opline->op2.jmp_addr); + } + break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: @@ -1047,6 +1052,11 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr case ZEND_ASSERT_CHECK: UNSERIALIZE_PTR(opline->op2.jmp_addr); break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + UNSERIALIZE_PTR(opline->op2.jmp_addr); + } + break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index f292ce09b0..a2549308ad 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -452,6 +452,11 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc case ZEND_ASSERT_CHECK: opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes]; break; + case ZEND_CATCH: + if (opline->extended_value != ZEND_LAST_CATCH) { + opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes]; + } + break; case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_FE_FETCH_R: diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c index 313bb4fae8..4b3bf4c668 100644 --- a/sapi/phpdbg/phpdbg_opcode.c +++ b/sapi/phpdbg/phpdbg_opcode.c @@ -115,7 +115,13 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *opline) /*{{{ */ /* RESULT */ switch (opline->opcode) { case ZEND_CATCH: - spprintf(&decode[3], 0, "%" PRIu32, opline->result.num); + if (opline->extended_value == ZEND_LAST_CATCH) { + if (decode[2]) { + efree(decode[2]); + decode[2] = NULL; + } + } + decode[3] = phpdbg_decode_op(ops, opline, &opline->result, opline->result_type); break; default: decode[3] = phpdbg_decode_op(ops, opline, &opline->result, opline->result_type); diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 005015d850..cdee919f79 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -760,9 +760,9 @@ PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zen return 1; } - do { + cur = &op_array->opcodes[catch]; + while (1) { zend_class_entry *ce; - cur = &op_array->opcodes[catch]; if (!(ce = CACHED_PTR(Z_CACHE_SLOT_P(RT_CONSTANT(cur, cur->op1))))) { ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(cur, cur->op1)), RT_CONSTANT(cur, cur->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD); @@ -773,8 +773,12 @@ PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *execute_data, zen return 1; } - catch += cur->extended_value / sizeof(zend_op); - } while (!cur->result.num); + if (cur->extended_value == ZEND_LAST_CATCH) { + return 0; + } + + cur = OP_JMP_ADDR(cur, cur->op2); + } return 0; } diff --git a/sapi/phpdbg/tests/exceptions_003.phpt b/sapi/phpdbg/tests/exceptions_003.phpt index 9d4abc0739..e78ff1d489 100644 --- a/sapi/phpdbg/tests/exceptions_003.phpt +++ b/sapi/phpdbg/tests/exceptions_003.phpt @@ -26,7 +26,7 @@ prompt> [L7 %s ECHO<1> "ok\n" 00009: } catch (Error $e) { prompt> ok [L7 %s FAST_RET ~%d try-catch(0) %s] -[L9 %s CATCH<-%d> "Error" $e 1 %s] +[L9 %s CATCH<1> "Error" $e %s] >00005: x(); 00006: } finally { 00007: print "ok\n"; diff --git a/sapi/phpdbg/tests/stepping_001.phpt b/sapi/phpdbg/tests/stepping_001.phpt index e8e32db0be..a7ab9e59aa 100644 --- a/sapi/phpdbg/tests/stepping_001.phpt +++ b/sapi/phpdbg/tests/stepping_001.phpt @@ -25,7 +25,7 @@ prompt> [L0 %s HANDLE_EXCEPTION 00005: } 00006: prompt> [L0 %s HANDLE_EXCEPTION %s] -[L9 %s CATCH<-%d> "Exception" $e 1 %s] +[L9 %s CATCH<1> "Exception" $e %s] >00008: foo(); 00009: } catch (Exception $e) { 00010: echo "ok"; |