From: Dmitry Stogov Date: Tue, 10 Nov 2015 16:13:54 +0000 (+0300) Subject: Changed meaning of "op2" for ZEND_FREE, ZEND_FE_FREE, ZEND_FAST_CALL, ZEND_FAST_RET. X-Git-Tag: php-7.1.0alpha1~827 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86a96f2cf1d6feb3682d600138c3b53cf65ff1b2;p=php Changed meaning of "op2" for ZEND_FREE, ZEND_FE_FREE, ZEND_FAST_CALL, ZEND_FAST_RET. Previously it was an instruction number. Now it's an index in op_array->try_cacth_array[]. --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 44d8d22e02..193370f48e 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -58,10 +58,7 @@ typedef struct _zend_loop_var { zend_uchar opcode; zend_uchar var_type; uint32_t var_num; - union { - uint32_t try_catch_offset; - uint32_t brk_cont_offset; - } u; + uint32_t try_catch_offset; } zend_loop_var; static inline void zend_alloc_cache_slot(uint32_t literal) { @@ -584,7 +581,7 @@ static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var info.opcode = free_opcode; info.var_type = loop_var->op_type; info.var_num = loop_var->u.op.var; - info.u.brk_cont_offset = CG(context).current_brk_cont; + info.try_catch_offset = CG(active_op_array)->last_try_catch; brk_cont_element->start = get_next_op_number(CG(active_op_array)); } else { info.opcode = ZEND_NOP; @@ -3574,7 +3571,7 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ opline->result.var = loop_var->var_num; SET_UNUSED(opline->op1); SET_UNUSED(opline->op2); - opline->op1.num = loop_var->u.try_catch_offset; + opline->op1.num = loop_var->try_catch_offset; } else if (loop_var->opcode == ZEND_RETURN) { /* Stack separator */ break; @@ -3592,7 +3589,7 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ opline->op1_type = loop_var->var_type; opline->op1.var = loop_var->var_num; SET_UNUSED(opline->op2); - opline->op2.num = loop_var->u.brk_cont_offset; + opline->op2.num = loop_var->try_catch_offset; opline->extended_value = ZEND_FREE_ON_RETURN; depth--; } @@ -4163,7 +4160,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */ fast_call.opcode = ZEND_FAST_CALL; fast_call.var_type = IS_TMP_VAR; fast_call.var_num = CG(context).fast_call_var; - fast_call.u.try_catch_offset = try_catch_offset; + fast_call.try_catch_offset = try_catch_offset; zend_stack_push(&CG(loop_var_stack), &fast_call); } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 4cf131af53..524eb5cb67 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -516,48 +516,52 @@ static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t op_num) { int i; - uint32_t finally_op_num = 0; + uint32_t finally_num = (uint32_t)-1; 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; + finally_num = i; } } - if (finally_op_num) { + if (finally_num != (uint32_t)-1) { /* Must be ZEND_FAST_CALL */ - ZEND_ASSERT(op_array->opcodes[finally_op_num - 2].opcode == ZEND_FAST_CALL); + ZEND_ASSERT(op_array->opcodes[op_array->try_catch_array[finally_num].finally_op - 2].opcode == ZEND_FAST_CALL); op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FROM_FINALLY; - op_array->opcodes[op_num].op2.opline_num = finally_op_num - 2; + op_array->opcodes[op_num].op2.num = finally_num; } } static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num) { int i; - uint32_t catch_op_num = 0, finally_op_num = 0; + uint32_t finally_num = (uint32_t)-1; + uint32_t catch_num = (uint32_t)-1; for (i = 0; i < op_array->last_try_catch; i++) { if (op_array->try_catch_array[i].try_op > op_num) { break; } if (op_num < op_array->try_catch_array[i].finally_op) { - finally_op_num = op_array->try_catch_array[i].finally_op; + finally_num = i; } if (op_num < op_array->try_catch_array[i].catch_op) { - catch_op_num = op_array->try_catch_array[i].catch_op; + catch_num = i; } } - if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { + if (finally_num != (uint32_t)-1 && + (catch_num == (uint32_t)-1 || + op_array->try_catch_array[catch_num].catch_op >= + op_array->try_catch_array[finally_num].finally_op)) { /* in case of unhandled exception return to upward finally block */ op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY; - op_array->opcodes[op_num].op2.opline_num = finally_op_num; - } else if (catch_op_num) { + op_array->opcodes[op_num].op2.num = finally_num; + } else if (catch_num != (uint32_t)-1) { /* in case of unhandled exception return to upward catch block */ op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH; - op_array->opcodes[op_num].op2.opline_num = catch_op_num; + op_array->opcodes[op_num].op2.num = catch_num; } } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 88bd9f2280..3c7e20213b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2711,7 +2711,7 @@ ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR) ZEND_VM_JMP(opline); } -ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY) +ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, TRY_CATCH) { USE_OPLINE @@ -2720,7 +2720,7 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY) +ZEND_VM_HANDLER(127, ZEND_FE_FREE, TMPVAR, TRY_CATCH) { zval *var; USE_OPLINE @@ -7239,6 +7239,7 @@ ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY) ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) { uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes; + uint32_t last_try_catch = EX(func)->op_array.last_try_catch; int i; uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; int in_finally = 0; @@ -7250,14 +7251,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if ((exc_opline->opcode == ZEND_FREE || exc_opline->opcode == ZEND_FE_FREE) && exc_opline->extended_value & ZEND_FREE_ON_RETURN) { /* exceptions thrown because of loop var destruction on return/break/... - * are logically thrown at the end of the foreach loop, so adjust the - * op_num. + * are logically thrown at the end of the foreach loop, + * so don't check the inner exception regions */ - op_num = EX(func)->op_array.brk_cont_array[exc_opline->op2.num].brk; + last_try_catch = exc_opline->op2.num; } } - for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { + for (i = 0; i < last_try_catch; i++) { if (EX(func)->op_array.try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; @@ -7679,7 +7680,7 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, JMP_ABS, FAST_CALL) +ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, TRY_CATCH, FAST_CALL) { USE_OPLINE zval *fast_call = EX_VAR(opline->result.var); @@ -7695,7 +7696,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, JMP_ABS, FAST_CALL) ZEND_VM_CONTINUE(); } -ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, JMP_ABS, FAST_RET) +ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH, FAST_RET) { USE_OPLINE zval *fast_call = EX_VAR(opline->op1.var); @@ -7704,7 +7705,7 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, JMP_ABS, FAST_RET) const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; ZEND_VM_SET_OPCODE(fast_ret + 1); if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { - fast_call->u2.lineno = fast_ret->op2.opline_num; + fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2; } ZEND_VM_CONTINUE(); } else { @@ -7712,15 +7713,19 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, JMP_ABS, FAST_RET) USE_OPLINE if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { - cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num); - ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); + uint32_t finally_op = EX(func)->op_array.try_catch_array[opline->op2.num].finally_op; + + cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, finally_op); + ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op]); ZEND_VM_CONTINUE(); } else { EG(exception) = Z_OBJ_P(fast_call); Z_OBJ_P(fast_call) = NULL; if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { - cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num); - ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); + uint32_t catch_op = EX(func)->op_array.try_catch_array[opline->op2.num].catch_op; + + cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, catch_op); + ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op]); ZEND_VM_CONTINUE(); } else { cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, 0); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index cc0193bfcd..42bd60b620 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1476,6 +1476,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes; + uint32_t last_try_catch = EX(func)->op_array.last_try_catch; int i; uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; int in_finally = 0; @@ -1487,14 +1488,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER( if ((exc_opline->opcode == ZEND_FREE || exc_opline->opcode == ZEND_FE_FREE) && exc_opline->extended_value & ZEND_FREE_ON_RETURN) { /* exceptions thrown because of loop var destruction on return/break/... - * are logically thrown at the end of the foreach loop, so adjust the - * op_num. + * are logically thrown at the end of the foreach loop, + * so don't check the inner exception regions */ - op_num = EX(func)->op_array.brk_cont_array[exc_opline->op2.num].brk; + last_try_catch = exc_opline->op2.num; } } - for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { + for (i = 0; i < last_try_catch; i++) { if (EX(func)->op_array.try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; @@ -1633,7 +1634,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno; ZEND_VM_SET_OPCODE(fast_ret + 1); if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) { - fast_call->u2.lineno = fast_ret->op2.opline_num; + fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2; } ZEND_VM_CONTINUE(); } else { @@ -1641,15 +1642,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC USE_OPLINE if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { - cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num); - ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); + uint32_t finally_op = EX(func)->op_array.try_catch_array[opline->op2.num].finally_op; + + cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, finally_op); + ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op]); ZEND_VM_CONTINUE(); } else { EG(exception) = Z_OBJ_P(fast_call); Z_OBJ_P(fast_call) = NULL; if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { - cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num); - ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]); + uint32_t catch_op = EX(func)->op_array.try_catch_array[opline->op2.num].catch_op; + + cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, catch_op); + ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op]); ZEND_VM_CONTINUE(); } else { cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, 0); diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index d55b876dba..fb6681a0c4 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -60,14 +60,14 @@ $vm_op_flags = array( "ZEND_VM_OP1_TMPVAR" => 1<<2, "ZEND_VM_OP1_NUM" => 1<<3, "ZEND_VM_OP1_JMP_ADDR" => 1<<4, - "ZEND_VM_OP1_JMP_ABS" => 1<<5, + "ZEND_VM_OP1_TRY_CATCH" => 1<<5, "ZEND_VM_OP2_SPEC" => 1<<8, "ZEND_VM_OP2_CONST" => 1<<9, "ZEND_VM_OP2_TMPVAR" => 1<<10, "ZEND_VM_OP2_NUM" => 1<<11, "ZEND_VM_OP2_JMP_ADDR" => 1<<12, - "ZEND_VM_OP2_JMP_ABS" => 1<<13, + "ZEND_VM_OP2_TRY_CATCH" => 1<<13, "ZEND_VM_EXT_NUM" => 1<<16, "ZEND_VM_EXT_VAR" => 1<<17, @@ -98,7 +98,7 @@ $vm_op_decode = array( "TMPVAR" => ZEND_VM_OP1_SPEC | ZEND_VM_OP1_TMPVAR, "NUM" => ZEND_VM_OP1_NUM, "JMP_ADDR" => ZEND_VM_OP1_JMP_ADDR, - "JMP_ABS" => ZEND_VM_OP1_JMP_ABS, + "TRY_CATCH" => ZEND_VM_OP1_TRY_CATCH, ); $vm_ext_decode = array( diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 70b3e81f84..d53ce5ecd9 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -277,7 +277,7 @@ static uint32_t zend_vm_opcodes_flags[182] = { 0x00000801, 0x00011003, 0x00010300, - 0x00000005, + 0x00002005, 0x00800703, 0x00010703, 0x02000007, @@ -334,7 +334,7 @@ static uint32_t zend_vm_opcodes_flags[182] = { 0x00000103, 0x00001003, 0x00040001, - 0x00000005, + 0x00002005, 0x00010700, 0x00000000, 0x00000000, diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 62dbe2205d..039f6d8d4e 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -33,13 +33,13 @@ #define ZEND_VM_OP1_TMPVAR 0x00000004 #define ZEND_VM_OP1_NUM 0x00000008 #define ZEND_VM_OP1_JMP_ADDR 0x00000010 -#define ZEND_VM_OP1_JMP_ABS 0x00000020 +#define ZEND_VM_OP1_TRY_CATCH 0x00000020 #define ZEND_VM_OP2_SPEC 0x00000100 #define ZEND_VM_OP2_CONST 0x00000200 #define ZEND_VM_OP2_TMPVAR 0x00000400 #define ZEND_VM_OP2_NUM 0x00000800 #define ZEND_VM_OP2_JMP_ADDR 0x00001000 -#define ZEND_VM_OP2_JMP_ABS 0x00002000 +#define ZEND_VM_OP2_TRY_CATCH 0x00002000 #define ZEND_VM_EXT_NUM 0x00010000 #define ZEND_VM_EXT_VAR 0x00020000 #define ZEND_VM_EXT_JMP_ADDR 0x00040000 diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index eeb263a434..4053fe7da4 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -125,18 +125,6 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz while (opline < end) { switch((unsigned)opline->opcode) { case ZEND_FAST_CALL: - START_BLOCK_OP(ZEND_OP1(opline).opline_num); - if (opline->extended_value) { - START_BLOCK_OP(ZEND_OP2(opline).opline_num); - } - START_BLOCK_OP(opno + 1); - break; - case ZEND_FAST_RET: - if (opline->extended_value) { - START_BLOCK_OP(ZEND_OP2(opline).opline_num); - } - START_BLOCK_OP(opno + 1); - break; case ZEND_JMP: case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: @@ -147,6 +135,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz case ZEND_GENERATOR_RETURN: case ZEND_EXIT: case ZEND_THROW: + case ZEND_FAST_RET: /* start new block from this+1 */ START_BLOCK_OP(opno + 1); break; @@ -272,21 +261,12 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz case ZEND_GENERATOR_RETURN: case ZEND_EXIT: case ZEND_THROW: - break; - case ZEND_FAST_CALL: - if (opline->extended_value) { - cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num]; - } - cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num]; - break; case ZEND_FAST_RET: - if (opline->extended_value) { - cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num]; - } break; case ZEND_JMP: cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num]; break; + case ZEND_FAST_CALL: case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num]; diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c index 44170c8c9e..a792090275 100644 --- a/sapi/phpdbg/phpdbg_opcode.c +++ b/sapi/phpdbg/phpdbg_opcode.c @@ -121,7 +121,7 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op) /*{{{ */ case ZEND_FAST_CALL: case ZEND_FAST_RET: if (op->extended_value != 0) { - spprintf(&decode[2], 0, "J%" PRIu32, op->op2.opline_num); + spprintf(&decode[2], 0, "%" PRIu32, op->op2.num); } break; diff --git a/sapi/phpdbg/tests/exceptions_003.phpt b/sapi/phpdbg/tests/exceptions_003.phpt index fffe7a9296..c83eb7517a 100644 --- a/sapi/phpdbg/tests/exceptions_003.phpt +++ b/sapi/phpdbg/tests/exceptions_003.phpt @@ -25,7 +25,7 @@ prompt> [L7 %s ECHO "ok " 00008: } 00009: } catch (Error $e) { prompt> ok -[L7 %s FAST_RET ~%d J7 %s] +[L7 %s FAST_RET ~%d 0 %s] [L9 %s CATCH "Error" $e 1 %s] >00005: x(); 00006: } finally {