} else {
int array_offset = CG(context).current_brk_cont;
zend_long nest_level = depth;
+ znode *loop_var = zend_stack_top(&CG(loop_var_stack));
do {
if (array_offset == -1) {
ast->kind == ZEND_AST_BREAK ? "break" : "continue",
depth, depth == 1 ? "" : "s");
}
+
+ if (nest_level > 1 && CG(active_op_array)->brk_cont_array[array_offset].start >= 0) {
+ generate_free_loop_var(loop_var);
+ loop_var--;
+ }
+
array_offset = CG(active_op_array)->brk_cont_array[array_offset].parent;
} while (--nest_level > 0);
}
}
}
+static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
+ int nest_levels = opline->op2.num;
+ int array_offset = opline->op1.num;
+ zend_brk_cont_element *jmp_to;
+ do {
+ jmp_to = &op_array->brk_cont_array[array_offset];
+ if (nest_levels > 1) {
+ array_offset = jmp_to->parent;
+ }
+ } while (--nest_levels > 0);
+
+ return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
+}
+
static void zend_resolve_finally_calls(zend_op_array *op_array)
{
uint32_t i, j;
break;
case ZEND_BRK:
case ZEND_CONT:
- {
- int nest_levels = opline->op2.num;
- int array_offset = opline->op1.num;
- zend_brk_cont_element *jmp_to;
-
- if (array_offset != -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);
- break;
- }
- }
+ zend_resolve_finally_call(op_array, i, zend_get_brk_cont_target(op_array, opline));
+ break;
case ZEND_GOTO:
if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) != IS_LONG) {
uint32_t num = opline->op2.constant;
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value);
break;
+ case ZEND_BRK:
+ case ZEND_CONT:
+ {
+ uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
+ opline->opcode = ZEND_JMP;
+ opline->op1.opline_num = jmp_target;
+ opline->op2.num = 0;
+ ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
+ }
+ break;
case ZEND_GOTO:
if (Z_TYPE_P(RT_CONSTANT(op_array, opline->op2)) != IS_LONG) {
zend_resolve_goto_label(op_array, opline, 1);