From: Dmitry Stogov Date: Mon, 11 Apr 2016 10:17:24 +0000 (+0300) Subject: Improve zend_leave_helper() by checking all rare conditions at once. X-Git-Tag: php-7.1.0alpha1~334^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8453b781136dd688de69eb2b6c86675a5a245847;p=php Improve zend_leave_helper() by checking all rare conditions at once. --- diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7a6974de09..7f2dd632b9 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2514,34 +2514,56 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) uint32_t call_info = EX_CALL_INFO(); if (EXPECTED(ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_NESTED_FUNCTION)) { - zend_object *object; - i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { - zend_clean_and_cache_symbol_table(EX(symbol_table)); - } - zend_vm_stack_free_extra_args_ex(call_info, execute_data); - old_execute_data = execute_data; - execute_data = EG(current_execute_data) = EX(prev_execute_data); - if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { - object = Z_OBJ(old_execute_data->This); + if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED))) { + if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + EG(current_execute_data) = EX(prev_execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(execute_data->This); #if 0 - if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { + if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { #else - if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { + if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { #endif - GC_REFCOUNT(object)--; - if (GC_REFCOUNT(object) == 1) { - zend_object_store_ctor_failed(object); + GC_REFCOUNT(object)--; + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object); + } } + OBJ_RELEASE(object); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype); } - OBJ_RELEASE(object); - } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { - OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype); + + zend_vm_stack_free_extra_args_ex(call_info, execute_data); + old_execute_data = execute_data; + execute_data = EX(prev_execute_data); + zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + } else { + EG(current_execute_data) = EX(prev_execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(execute_data->This); +#if 0 + if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { +#endif + GC_REFCOUNT(object)--; + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object); + } + } + OBJ_RELEASE(object); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype); + } + EG(vm_stack_top) = (zval*)execute_data; + execute_data = EX(prev_execute_data); } - EG(scope) = EX(func)->op_array.scope; - zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + EG(scope) = EX(func)->op_array.scope; if (UNEXPECTED(EG(exception) != NULL)) { const zend_op *old_opline = EX(opline); @@ -2554,8 +2576,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) LOAD_NEXT_OPLINE(); ZEND_VM_LEAVE(); - } - if (EXPECTED((ZEND_CALL_KIND_EX(call_info) & ZEND_CALL_TOP) == 0)) { + } else if (EXPECTED((ZEND_CALL_KIND_EX(call_info) & ZEND_CALL_TOP) == 0)) { zend_detach_symbol_table(execute_data); destroy_op_array(&EX(func)->op_array); efree_size(EX(func), sizeof(zend_op_array)); @@ -2574,14 +2595,17 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } else { if (ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_TOP_FUNCTION) { i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { - zend_clean_and_cache_symbol_table(EX(symbol_table)); + if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + zend_vm_stack_free_extra_args_ex(call_info, execute_data); } - zend_vm_stack_free_extra_args_ex(call_info, execute_data); EG(current_execute_data) = EX(prev_execute_data); if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype); } + ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -2597,9 +2621,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) old_execute_data = old_execute_data->prev_execute_data; } EG(current_execute_data) = EX(prev_execute_data); + ZEND_VM_RETURN(); } - - ZEND_VM_RETURN(); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 0b3bafecf0..8e2541f78c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -475,34 +475,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ uint32_t call_info = EX_CALL_INFO(); if (EXPECTED(ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_NESTED_FUNCTION)) { - zend_object *object; - i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { - zend_clean_and_cache_symbol_table(EX(symbol_table)); - } - zend_vm_stack_free_extra_args_ex(call_info, execute_data); - old_execute_data = execute_data; - execute_data = EG(current_execute_data) = EX(prev_execute_data); - if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { - object = Z_OBJ(old_execute_data->This); + if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED))) { + if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + EG(current_execute_data) = EX(prev_execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(execute_data->This); #if 0 - if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { + if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { #else - if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { + if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { #endif - GC_REFCOUNT(object)--; - if (GC_REFCOUNT(object) == 1) { - zend_object_store_ctor_failed(object); + GC_REFCOUNT(object)--; + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object); + } } + OBJ_RELEASE(object); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype); } - OBJ_RELEASE(object); - } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { - OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype); + + zend_vm_stack_free_extra_args_ex(call_info, execute_data); + old_execute_data = execute_data; + execute_data = EX(prev_execute_data); + zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + } else { + EG(current_execute_data) = EX(prev_execute_data); + if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { + zend_object *object = Z_OBJ(execute_data->This); +#if 0 + if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { +#endif + GC_REFCOUNT(object)--; + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object); + } + } + OBJ_RELEASE(object); + } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE((zend_object*)execute_data->func->op_array.prototype); + } + EG(vm_stack_top) = (zval*)execute_data; + execute_data = EX(prev_execute_data); } - EG(scope) = EX(func)->op_array.scope; - zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); + EG(scope) = EX(func)->op_array.scope; if (UNEXPECTED(EG(exception) != NULL)) { const zend_op *old_opline = EX(opline); @@ -515,8 +537,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ LOAD_NEXT_OPLINE(); ZEND_VM_LEAVE(); - } - if (EXPECTED((ZEND_CALL_KIND_EX(call_info) & ZEND_CALL_TOP) == 0)) { + } else if (EXPECTED((ZEND_CALL_KIND_EX(call_info) & ZEND_CALL_TOP) == 0)) { zend_detach_symbol_table(execute_data); destroy_op_array(&EX(func)->op_array); efree_size(EX(func), sizeof(zend_op_array)); @@ -535,14 +556,17 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ } else { if (ZEND_CALL_KIND_EX(call_info) == ZEND_CALL_TOP_FUNCTION) { i_free_compiled_variables(execute_data); - if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { - zend_clean_and_cache_symbol_table(EX(symbol_table)); + if (UNEXPECTED(call_info & (ZEND_CALL_FREE_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS))) { + if (UNEXPECTED(call_info & ZEND_CALL_FREE_SYMBOL_TABLE)) { + zend_clean_and_cache_symbol_table(EX(symbol_table)); + } + zend_vm_stack_free_extra_args_ex(call_info, execute_data); } - zend_vm_stack_free_extra_args_ex(call_info, execute_data); EG(current_execute_data) = EX(prev_execute_data); if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype); } + ZEND_VM_RETURN(); } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { zend_array *symbol_table = EX(symbol_table); @@ -558,9 +582,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ old_execute_data = old_execute_data->prev_execute_data; } EG(current_execute_data) = EX(prev_execute_data); + ZEND_VM_RETURN(); } - - ZEND_VM_RETURN(); } }