From: Dmitry Stogov <dmitry@zend.com> Date: Wed, 5 Dec 2012 09:23:37 +0000 (+0400) Subject: Slight performance improvement X-Git-Tag: php-5.5.0alpha2~44 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fa30e4754bea0d0c6a048ca029c543ddcaf3b84f;p=php Slight performance improvement --- diff --git a/UPGRADING b/UPGRADING index 170c6de51d..b01a399697 100755 --- a/UPGRADING +++ b/UPGRADING @@ -54,7 +54,7 @@ PHP 5.5 UPGRADE NOTES stores new offsets in op_array->opcodes[*].op?.num. You can use macros EX_TMP_VAR() and EX_TMP_VAR_NUM() to access temp_variable by offset or number. You can convert number to offset using EX_TMP_VAR_NUM(0, num) or - offset to number (EX_TMP_VAR(0,offset)-EX_TMP_VAR_NUM(0,0)). + offset to number (EX_TMP_VAR_NUM(0,0)-EX_TMP_VAR(0,offset)). - Removed execute_data->CVs field. The VM compiled variables always allocated immediately after execute_data structure. Now they are accessed by offset from the execute_data base pointer (instead of execute_data->CVs). You can diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1c8e61cc3a..d260953bd7 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -167,6 +167,9 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC) #define DECODE_CTOR(ce) \ ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT))) +#undef EX +#define EX(element) execute_data->element + ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data, zend_uint var) { return EX_CV(var); @@ -1488,62 +1491,6 @@ ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_i } } -#define ZEND_VM_NEXT_OPCODE() \ - CHECK_SYMBOL_TABLES() \ - ZEND_VM_INC_OPCODE(); \ - ZEND_VM_CONTINUE() - -#define ZEND_VM_SET_OPCODE(new_op) \ - CHECK_SYMBOL_TABLES() \ - OPLINE = new_op - -#define ZEND_VM_JMP(new_op) \ - if (EXPECTED(!EG(exception))) { \ - ZEND_VM_SET_OPCODE(new_op); \ - } else { \ - LOAD_OPLINE(); \ - } \ - ZEND_VM_CONTINUE() - -#define ZEND_VM_INC_OPCODE() \ - OPLINE++ - -#ifdef __GNUC__ -# define ZEND_VM_GUARD(name) __asm__("#" #name) -#else -# define ZEND_VM_GUARD(name) -#endif - -#include "zend_vm_execute.h" - -ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler) -{ - if (opcode != ZEND_USER_OPCODE) { - if (handler == NULL) { - /* restore the original handler */ - zend_user_opcodes[opcode] = opcode; - } else { - zend_user_opcodes[opcode] = ZEND_USER_OPCODE; - } - zend_user_opcode_handlers[opcode] = handler; - return SUCCESS; - } - return FAILURE; -} - -ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) -{ - return zend_user_opcode_handlers[opcode]; -} - -ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { - return get_zval_ptr(op_type, node, execute_data, should_free, type); -} - -ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { - return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type); -} - void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{ */ { if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) { @@ -1558,14 +1505,22 @@ void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{ } /* }}} */ -void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ +static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ { - int i; - for (i = 0; i < EX(op_array)->last_var; ++i) { - if (EX_CV(i)) { - zval_ptr_dtor(EX_CV(i)); + zval ***cv = EX_CV_NUM(execute_data, 0); + zval ***end = cv + EX(op_array)->last_var; + while (cv != end) { + if (*cv) { + zval_ptr_dtor(*cv); } - } + cv++; + } +} +/* }}} */ + +void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ +{ + i_free_compiled_variables(execute_data); } /* }}} */ @@ -1611,7 +1566,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ * +----------------------------------------+ */ -zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ +static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ { zend_execute_data *execute_data; @@ -1720,6 +1675,68 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra } /* }}} */ +zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ +{ + return i_create_execute_data_from_op_array(op_array, nested TSRMLS_CC); +} +/* }}} */ + +#define ZEND_VM_NEXT_OPCODE() \ + CHECK_SYMBOL_TABLES() \ + ZEND_VM_INC_OPCODE(); \ + ZEND_VM_CONTINUE() + +#define ZEND_VM_SET_OPCODE(new_op) \ + CHECK_SYMBOL_TABLES() \ + OPLINE = new_op + +#define ZEND_VM_JMP(new_op) \ + if (EXPECTED(!EG(exception))) { \ + ZEND_VM_SET_OPCODE(new_op); \ + } else { \ + LOAD_OPLINE(); \ + } \ + ZEND_VM_CONTINUE() + +#define ZEND_VM_INC_OPCODE() \ + OPLINE++ + +#ifdef __GNUC__ +# define ZEND_VM_GUARD(name) __asm__("#" #name) +#else +# define ZEND_VM_GUARD(name) +#endif + +#include "zend_vm_execute.h" + +ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler) +{ + if (opcode != ZEND_USER_OPCODE) { + if (handler == NULL) { + /* restore the original handler */ + zend_user_opcodes[opcode] = opcode; + } else { + zend_user_opcodes[opcode] = ZEND_USER_OPCODE; + } + zend_user_opcode_handlers[opcode] = handler; + return SUCCESS; + } + return FAILURE; +} + +ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) +{ + return zend_user_opcode_handlers[opcode]; +} + +ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { + return get_zval_ptr(op_type, node, execute_data, should_free, type); +} + +ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { + return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type); +} + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c309ca05de..2b65275fa6 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1852,7 +1852,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) } /* Generators go throw a different cleanup process */ - if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) { + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { /* The generator object is stored in return_value_ptr_ptr */ zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); @@ -1866,7 +1866,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; if (!EG(active_symbol_table)) { - zend_free_compiled_variables(execute_data); + i_free_compiled_variables(execute_data); } if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bce82ac4e5..5971cc9047 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -326,9 +326,6 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o #define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC -#undef EX -#define EX(element) execute_data->element - ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) { @@ -340,6 +337,11 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) original_in_execution = EG(in_execution); EG(in_execution) = 1; + if (0) { +zend_vm_enter: + execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); + } + LOAD_REGS(); LOAD_OPLINE(); @@ -357,7 +359,7 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) EG(in_execution) = original_in_execution; return; case 2: - execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); + goto zend_vm_enter; break; case 3: execute_data = EG(current_execute_data); @@ -376,7 +378,7 @@ ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC) if (EG(exception)) { return; } - zend_execute_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); + zend_execute_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); } static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) @@ -391,7 +393,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) } /* Generators go throw a different cleanup process */ - if (EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) { + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { /* The generator object is stored in return_value_ptr_ptr */ zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); @@ -405,7 +407,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; if (!EG(active_symbol_table)) { - zend_free_compiled_variables(execute_data); + i_free_compiled_variables(execute_data); } if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index eb18580b21..13fd88e2d8 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -12,6 +12,11 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC) original_in_execution = EG(in_execution); EG(in_execution) = 1; + if (0) { +zend_vm_enter: + execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); + } + LOAD_REGS(); LOAD_OPLINE(); @@ -36,7 +41,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) if (EG(exception)) { return; } - zend_{%EXECUTOR_NAME%}_ex(zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); + zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); } {%EXTERNAL_EXECUTOR%} diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 6c9dcafba7..b56dd70f40 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -839,8 +839,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_LEAVE() return 3\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); break; case ZEND_VM_KIND_SWITCH: out($f,"\n"); @@ -863,12 +861,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define LOAD_REGS()\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); - out($f,"#define ZEND_VM_ENTER() execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); LOAD_REGS(); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_ENTER() goto zend_vm_enter\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); break; case ZEND_VM_KIND_GOTO: out($f,"\n"); @@ -891,12 +887,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define LOAD_REGS()\n"); out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n"); out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); - out($f,"#define ZEND_VM_ENTER() execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); LOAD_REGS(); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); + out($f,"#define ZEND_VM_ENTER() goto zend_vm_enter\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); break; } break; @@ -965,7 +959,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, $m[1]."\t\tEG(in_execution) = original_in_execution;\n". $m[1]."\t\treturn;\n". $m[1]."\tcase 2:\n" . - $m[1]."\t\texecute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC);\n". + $m[1]."\t\tgoto zend_vm_enter;\n". $m[1]."\t\tbreak;\n" . $m[1]."\tcase 3:\n" . $m[1]."\t\texecute_data = EG(current_execute_data);\n". @@ -1215,8 +1209,6 @@ function gen_vm($def, $skel) { // Generate un-specialized executor if (ZEND_VM_OLD_EXECUTOR) { out($f,"\n/* Old executor */\n\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data.element\n\n"); out($f,"#undef ZEND_VM_CONTINUE\n\n"); out($f,"#undef ZEND_VM_RETURN\n\n"); out($f,"#undef ZEND_VM_ENTER\n\n"); @@ -1289,8 +1281,6 @@ function gen_vm($def, $skel) { out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n"); out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); out($f,"#undef ZEND_VM_CONTINUE\n"); out($f,"#undef ZEND_VM_RETURN\n"); out($f,"#undef ZEND_VM_ENTER\n");