}
}
- if (EX(call) >= EX(call_slots)) {
- call_slot *call = EX(call);
+ if (UNEXPECTED(EX(call))) {
+ zend_execute_data *call = EX(call);
+ zend_op *opline = EX(func)->op_array.opcodes + op_num;
+ int level;
+ int do_exit;
+
do {
- if (call->object) {
- if (call->is_ctor_call) {
- if (call->is_ctor_result_used) {
- Z_DELREF_P(call->object);
+ /* If the exception was thrown during a function call there might be
+ * arguments pushed to the stack that have to be dtor'ed. */
+
+ /* find the number of actually passed arguments */
+ level = 0;
+ do_exit = 0;
+ do {
+ switch (opline->opcode) {
+ case ZEND_DO_FCALL:
+ case ZEND_DO_ICALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ level++;
+ break;
+ case ZEND_INIT_FCALL:
+ case ZEND_INIT_FCALL_BY_NAME:
+ case ZEND_INIT_NS_FCALL_BY_NAME:
+ case ZEND_INIT_DYNAMIC_CALL:
+ case ZEND_INIT_USER_CALL:
+ case ZEND_INIT_METHOD_CALL:
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_NEW:
+ if (level == 0) {
+ ZEND_CALL_NUM_ARGS(call) = 0;
+ do_exit = 1;
+ }
+ level--;
+ break;
+ case ZEND_SEND_VAL:
+ case ZEND_SEND_VAL_EX:
+ case ZEND_SEND_VAR:
+ case ZEND_SEND_VAR_EX:
+ case ZEND_SEND_REF:
+ case ZEND_SEND_VAR_NO_REF:
+ case ZEND_SEND_USER:
+ if (level == 0) {
+ ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
+ do_exit = 1;
+ }
+ break;
+ case ZEND_SEND_ARRAY:
+ case ZEND_SEND_UNPACK:
+ if (level == 0) {
+ do_exit = 1;
+ }
+ break;
+ }
+ if (!do_exit) {
+ opline--;
+ }
+ } while (!do_exit);
+ if (call->prev_execute_data) {
+ /* skip current call region */
+ level = 0;
+ do_exit = 0;
+ do {
+ switch (opline->opcode) {
+ case ZEND_DO_FCALL:
+ case ZEND_DO_ICALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ level++;
+ break;
+ case ZEND_INIT_FCALL:
+ case ZEND_INIT_FCALL_BY_NAME:
+ case ZEND_INIT_NS_FCALL_BY_NAME:
+ case ZEND_INIT_DYNAMIC_CALL:
+ case ZEND_INIT_USER_CALL:
+ case ZEND_INIT_METHOD_CALL:
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_NEW:
+ if (level == 0) {
+ do_exit = 1;
+ }
+ level--;
+ break;
+ }
+ opline--;
+ } while (!do_exit);
+ }
+
+ zend_vm_stack_free_args(EX(call));
+
+ if (Z_OBJ(call->This)) {
+ if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
+ if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
+ GC_REFCOUNT(Z_OBJ(call->This))--;
}
- if (Z_REFCOUNT_P(call->object) == 1) {
- zend_object_store_ctor_failed(call->object TSRMLS_CC);
+ if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
+ zend_object_store_ctor_failed(Z_OBJ(call->This));
}
}
- zval_ptr_dtor(&call->object);
+ OBJ_RELEASE(Z_OBJ(call->This));
}
- if (call->fbc->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
- efree((char *) call->fbc->common.function_name);
- efree(call->fbc);
++ if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
++ zend_string_release(call->func->common.function_name);
++ efree(call->func);
+ }
- call--;
- } while (call >= EX(call_slots));
- EX(call) = NULL;
++
+ EX(call) = call->prev_execute_data;
+ zend_vm_stack_free_call_frame(call);
+ call = EX(call);
+ } while (call);
}
- for (i=0; i<EX(op_array)->last_brk_cont; i++) {
- if (EX(op_array)->brk_cont_array[i].start < 0) {
+ for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
+ if (EX(func)->op_array.brk_cont_array[i].start < 0) {
continue;
- } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
+ } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
/* further blocks will not be relevant... */
break;
- } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+ } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
if (!catch_op_num ||
- catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
- zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
+ catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
+ zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
- switch (brk_opline->opcode) {
- case ZEND_SWITCH_FREE:
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
- }
- break;
- case ZEND_FREE:
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
+ if (brk_opline->opcode == ZEND_FREE) {
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
+ }
+ } else if (brk_opline->opcode == ZEND_FE_FREE) {
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval *var = EX_VAR(brk_opline->op1.var);
+ if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
+ zend_hash_iterator_del(Z_FE_ITER_P(var));
}
- break;
+ zval_ptr_dtor_nogc(var);
+ }
+ } else if (brk_opline->opcode == ZEND_END_SILENCE) {
+ /* restore previous error_reporting value */
+ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
+ EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
+ }
}
}
}
}
}
- if (EX(call) >= EX(call_slots)) {
- call_slot *call = EX(call);
+ if (UNEXPECTED(EX(call))) {
+ zend_execute_data *call = EX(call);
+ zend_op *opline = EX(func)->op_array.opcodes + op_num;
+ int level;
+ int do_exit;
+
do {
- if (call->object) {
- if (call->is_ctor_call) {
- if (call->is_ctor_result_used) {
- Z_DELREF_P(call->object);
+ /* If the exception was thrown during a function call there might be
+ * arguments pushed to the stack that have to be dtor'ed. */
+
+ /* find the number of actually passed arguments */
+ level = 0;
+ do_exit = 0;
+ do {
+ switch (opline->opcode) {
+ case ZEND_DO_FCALL:
+ case ZEND_DO_ICALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ level++;
+ break;
+ case ZEND_INIT_FCALL:
+ case ZEND_INIT_FCALL_BY_NAME:
+ case ZEND_INIT_NS_FCALL_BY_NAME:
+ case ZEND_INIT_DYNAMIC_CALL:
+ case ZEND_INIT_USER_CALL:
+ case ZEND_INIT_METHOD_CALL:
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_NEW:
+ if (level == 0) {
+ ZEND_CALL_NUM_ARGS(call) = 0;
+ do_exit = 1;
+ }
+ level--;
+ break;
+ case ZEND_SEND_VAL:
+ case ZEND_SEND_VAL_EX:
+ case ZEND_SEND_VAR:
+ case ZEND_SEND_VAR_EX:
+ case ZEND_SEND_REF:
+ case ZEND_SEND_VAR_NO_REF:
+ case ZEND_SEND_USER:
+ if (level == 0) {
+ ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
+ do_exit = 1;
+ }
+ break;
+ case ZEND_SEND_ARRAY:
+ case ZEND_SEND_UNPACK:
+ if (level == 0) {
+ do_exit = 1;
+ }
+ break;
+ }
+ if (!do_exit) {
+ opline--;
+ }
+ } while (!do_exit);
+ if (call->prev_execute_data) {
+ /* skip current call region */
+ level = 0;
+ do_exit = 0;
+ do {
+ switch (opline->opcode) {
+ case ZEND_DO_FCALL:
+ case ZEND_DO_ICALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ level++;
+ break;
+ case ZEND_INIT_FCALL:
+ case ZEND_INIT_FCALL_BY_NAME:
+ case ZEND_INIT_NS_FCALL_BY_NAME:
+ case ZEND_INIT_DYNAMIC_CALL:
+ case ZEND_INIT_USER_CALL:
+ case ZEND_INIT_METHOD_CALL:
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_NEW:
+ if (level == 0) {
+ do_exit = 1;
+ }
+ level--;
+ break;
+ }
+ opline--;
+ } while (!do_exit);
+ }
+
+ zend_vm_stack_free_args(EX(call));
+
+ if (Z_OBJ(call->This)) {
+ if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
+ if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
+ GC_REFCOUNT(Z_OBJ(call->This))--;
}
- if (Z_REFCOUNT_P(call->object) == 1) {
- zend_object_store_ctor_failed(call->object TSRMLS_CC);
+ if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
+ zend_object_store_ctor_failed(Z_OBJ(call->This));
}
}
- zval_ptr_dtor(&call->object);
+ OBJ_RELEASE(Z_OBJ(call->This));
}
- if (call->fbc->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
- efree((char *) call->fbc->common.function_name);
- efree(call->fbc);
++ if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
++ zend_string_release(call->func->common.function_name);
++ efree(call->func);
+ }
- call--;
- } while (call >= EX(call_slots));
- EX(call) = NULL;
++
+ EX(call) = call->prev_execute_data;
+ zend_vm_stack_free_call_frame(call);
+ call = EX(call);
+ } while (call);
}
- for (i=0; i<EX(op_array)->last_brk_cont; i++) {
- if (EX(op_array)->brk_cont_array[i].start < 0) {
+ for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
+ if (EX(func)->op_array.brk_cont_array[i].start < 0) {
continue;
- } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
+ } else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
/* further blocks will not be relevant... */
break;
- } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+ } else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
if (!catch_op_num ||
- catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
- zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
+ catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
+ zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
- switch (brk_opline->opcode) {
- case ZEND_SWITCH_FREE:
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr);
- }
- break;
- case ZEND_FREE:
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var);
+ if (brk_opline->opcode == ZEND_FREE) {
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
+ }
+ } else if (brk_opline->opcode == ZEND_FE_FREE) {
+ if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ zval *var = EX_VAR(brk_opline->op1.var);
+ if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
+ zend_hash_iterator_del(Z_FE_ITER_P(var));
}
- break;
+ zval_ptr_dtor_nogc(var);
+ }
+ } else if (brk_opline->opcode == ZEND_END_SILENCE) {
+ /* restore previous error_reporting value */
+ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
+ EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
+ }
}
}
}