From e1ab2cfe1c4c53798e6fdfd49320650dac240945 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 24 Mar 2015 12:21:06 +0300 Subject: [PATCH] Introduce ZEND_ASSUME() macro to help optimizing code. Reuse ZEND_ASSERT() conditions for optimization. --- Zend/zend_portability.h | 36 ++++++++++++++++++++++++------------ Zend/zend_vm_def.h | 6 ++++++ Zend/zend_vm_execute.h | 6 ++++++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 07431414374..05ef0df53ef 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -78,14 +78,35 @@ #include #endif +/* GCC x.y.z supplies __GNUC__ = x and __GNUC_MINOR__ = y */ +#ifdef __GNUC__ +# define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#else +# define ZEND_GCC_VERSION 0 +#endif + +#if defined(ZEND_WIN32) +# define ZEND_ASSUME(c) __assume(c) +#elif defined(__GNUC__) && PHP_HAVE_BUILTIN_EXPECT && ZEND_GCC_VERSION >= 4005 +# define ZEND_ASSUME(c) do { \ + if (__builtin_expect(!(c), 0)) __builtin_unreachable(); \ + } while (0) +#else +# define ZEND_ASSUME(c) +#endif + +#if ZEND_DEBUG +# define ZEND_ASSERT(c) assert(c) +#else +# define ZEND_ASSERT(c) ZEND_ASSUME(c) +#endif + /* Only use this macro if you know for sure that all of the switches values are covered by its case statements */ #if ZEND_DEBUG # define EMPTY_SWITCH_DEFAULT_CASE() default: ZEND_ASSERT(0); break; -#elif defined(ZEND_WIN32) -# define EMPTY_SWITCH_DEFAULT_CASE() default: __assume(0); break; #else -# define EMPTY_SWITCH_DEFAULT_CASE() +# define EMPTY_SWITCH_DEFAULT_CASE() default: ZEND_ASSUME(0); break; #endif /* all HAVE_XXX test have to be after the include of zend_config above */ @@ -145,13 +166,6 @@ char *alloca(); # define __has_attribute(x) 0 #endif -/* GCC x.y.z supplies __GNUC__ = x and __GNUC_MINOR__ = y */ -#ifdef __GNUC__ -# define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) -#else -# define ZEND_GCC_VERSION 0 -#endif - #if ZEND_GCC_VERSION >= 2096 # define ZEND_ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) #else @@ -337,7 +351,6 @@ char *alloca(); # define ZEND_FILE_LINE_EMPTY_CC , ZEND_FILE_LINE_EMPTY_C # define ZEND_FILE_LINE_ORIG_RELAY_C __zend_orig_filename, __zend_orig_lineno # define ZEND_FILE_LINE_ORIG_RELAY_CC , ZEND_FILE_LINE_ORIG_RELAY_C -# define ZEND_ASSERT(c) assert(c) #else # define ZEND_FILE_LINE_D # define ZEND_FILE_LINE_DC @@ -351,7 +364,6 @@ char *alloca(); # define ZEND_FILE_LINE_EMPTY_CC # define ZEND_FILE_LINE_ORIG_RELAY_C # define ZEND_FILE_LINE_ORIG_RELAY_CC -# define ZEND_ASSERT(c) #endif /* ZEND_DEBUG */ #if ZEND_DEBUG diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 95408ebdd40..ed4c7191a7a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3229,10 +3229,12 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) fbc->internal_function.handler(call, ret); +#if ZEND_DEBUG ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); +#endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3357,10 +3359,12 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) fbc->internal_function.handler(call, ret); +#if ZEND_DEBUG ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); +#endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3494,10 +3498,12 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) zend_execute_internal(call, ret); } +#if ZEND_DEBUG ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); +#endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index eb551ee15fc..ebec22ed84a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -560,10 +560,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC fbc->internal_function.handler(call, ret); +#if ZEND_DEBUG ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); +#endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -688,10 +690,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( fbc->internal_function.handler(call, ret); +#if ZEND_DEBUG ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); +#endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -825,10 +829,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC zend_execute_internal(call, ret); } +#if ZEND_DEBUG ZEND_ASSERT( !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); +#endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call);