Previously it was an instruction number.
Now it's an index in op_array->try_cacth_array[].
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) {
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;
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;
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--;
}
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);
}
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;
}
}
ZEND_VM_JMP(opline);
}
-ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY)
+ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, TRY_CATCH)
{
USE_OPLINE
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
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;
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;
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);
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);
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 {
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);
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;
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;
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 {
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);
"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,
"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(
0x00000801,
0x00011003,
0x00010300,
- 0x00000005,
+ 0x00002005,
0x00800703,
0x00010703,
0x02000007,
0x00000103,
0x00001003,
0x00040001,
- 0x00000005,
+ 0x00002005,
0x00010700,
0x00000000,
0x00000000,
#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
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:
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;
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];
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;
00008: }
00009: } catch (Error $e) {
prompt> ok
-[L7 %s FAST_RET<TO_CATCH> ~%d J7 %s]
+[L7 %s FAST_RET<TO_CATCH> ~%d 0 %s]
[L9 %s CATCH "Error" $e 1 %s]
>00005: x();
00006: } finally {