From: Nikita Popov Date: Tue, 10 Mar 2015 17:26:09 +0000 (+0100) Subject: Merge branch 'PHP-5.6' X-Git-Tag: PRE_PHP7_NSAPI_REMOVAL~715 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00985a975d633a1649be2d67113c2ba916a684bc;p=php Merge branch 'PHP-5.6' Conflicts: Zend/zend_vm_def.h Zend/zend_vm_execute.h --- 00985a975d633a1649be2d67113c2ba916a684bc diff --cc Zend/zend_vm_def.h index 5c99f1c456,0fed90214d..56661276e5 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -6276,141 -5241,51 +6276,146 @@@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPT } } - 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; ilast_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)); + } } } } diff --cc Zend/zend_vm_execute.h index 621529ffa2,eaa22a6205..48665b81af --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@@ -1417,141 -1200,51 +1417,146 @@@ static int ZEND_FASTCALL ZEND_HANDLE_E } } - 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; ilast_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)); + } } } }