From 8a6d73b084de819fc2f15cad52e8706a94a1c9f9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 18 Aug 2010 13:58:13 +0000 Subject: [PATCH] improved performance of @ (silence) operator --- NEWS | 1 + Zend/zend_globals.h | 3 +++ Zend/zend_ini.c | 2 ++ Zend/zend_ini.h | 2 -- Zend/zend_vm_def.h | 38 +++++++++++++++++++++++++++++++++++--- Zend/zend_vm_execute.h | 38 +++++++++++++++++++++++++++++++++++--- 6 files changed, 76 insertions(+), 8 deletions(-) diff --git a/NEWS b/NEWS index 3d5454f9f2..d4c448531b 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,7 @@ flag any more. Thit is very rare and useless case. ZEND_FREE might be required after them instead. . improved performance of FastCGI request parsing + . improved performance of @ (silence) operator - Added concept of interned strings. All strings constants known at compile time are allocated in a single copy and never changed. (Dmitry) - Added an optimization which saves memory and emalloc/efree calls for empty diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 4446705780..dfc8075bdd 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -69,6 +69,8 @@ typedef struct _zend_declarables { } zend_declarables; typedef struct _zend_vm_stack *zend_vm_stack; +typedef struct _zend_ini_entry zend_ini_entry; + struct _zend_compiler_globals { zend_stack bp_stack; @@ -248,6 +250,7 @@ struct _zend_executor_globals { HashTable *ini_directives; HashTable *modified_ini_directives; + zend_ini_entry *error_reporting_ini_entry; zend_objects_store objects_store; zval *exception, *prev_exception; diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 60af9acf40..f30f01a5e1 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -92,6 +92,7 @@ ZEND_API int zend_ini_startup(TSRMLS_D) /* {{{ */ EG(ini_directives) = registered_zend_ini_directives; EG(modified_ini_directives) = NULL; + EG(error_reporting_ini_entry) = NULL; if (zend_hash_init_ex(registered_zend_ini_directives, 100, NULL, NULL, 1, 0) == FAILURE) { return FAILURE; } @@ -133,6 +134,7 @@ ZEND_API int zend_copy_ini_directives(TSRMLS_D) /* {{{ */ zend_ini_entry ini_entry; EG(modified_ini_directives) = NULL; + EG(error_reporting_ini_entry) = NULL; EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable)); if (zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0) == FAILURE) { return FAILURE; diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index ccc5414632..397dbaef21 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -57,8 +57,6 @@ #endif -typedef struct _zend_ini_entry zend_ini_entry; - #define ZEND_INI_MH(name) int name(zend_ini_entry *entry, char *new_value, uint new_value_length, void *mh_arg1, void *mh_arg2, void *mh_arg3, int stage TSRMLS_DC) #define ZEND_INI_DISP(name) void name(zend_ini_entry *ini_entry, int type) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f25599f5bc..bae4c995ff 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4520,7 +4520,30 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY) } if (EG(error_reporting)) { - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); + do { + EG(error_reporting) = 0; + if (!EG(error_reporting_ini_entry)) { + if (UNEXPECTED(zend_hash_find(EG(ini_directives), "error_reporting", sizeof("error_reporting"), (void **) &EG(error_reporting_ini_entry)) == FAILURE)) { + break; + } + } + if (!EG(error_reporting_ini_entry)->modified) { + if (!EG(modified_ini_directives)) { + ALLOC_HASHTABLE(EG(modified_ini_directives)); + zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0); + } + if (EXPECTED(zend_hash_add(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting"), &EG(error_reporting_ini_entry), sizeof(zend_ini_entry*), NULL) == SUCCESS)) { + EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value; + EG(error_reporting_ini_entry)->orig_value_length = EG(error_reporting_ini_entry)->value_length; + EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable; + EG(error_reporting_ini_entry)->modified = 1; + } + } else if (EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value) { + efree(EG(error_reporting_ini_entry)->value); + } + EG(error_reporting_ini_entry)->value = estrndup("0", sizeof("0")-1); + EG(error_reporting_ini_entry)->value_length = sizeof("0")-1; + } while (0); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4542,9 +4565,18 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY) if (!EG(error_reporting) && Z_LVAL(EX_T(opline->op1.var).tmp_var) != 0) { Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.var).tmp_var); + EG(error_reporting) = Z_LVAL(restored_error_reporting); convert_to_string(&restored_error_reporting); - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); - zendi_zval_dtor(restored_error_reporting); + if (EXPECTED(EG(error_reporting_ini_entry) != NULL)) { + if (EXPECTED(EG(error_reporting_ini_entry)->modified && + EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value)) { + efree(EG(error_reporting_ini_entry)->value); + } + EG(error_reporting_ini_entry)->value = Z_STRVAL(restored_error_reporting); + EG(error_reporting_ini_entry)->value_length = Z_STRLEN(restored_error_reporting); + } else { + zendi_zval_dtor(restored_error_reporting); + } } if (EX(old_error_reporting) == &EX_T(opline->op1.var).tmp_var) { EX(old_error_reporting) = NULL; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 87cbfbc5f2..3b07493c52 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -848,7 +848,30 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR } if (EG(error_reporting)) { - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); + do { + EG(error_reporting) = 0; + if (!EG(error_reporting_ini_entry)) { + if (UNEXPECTED(zend_hash_find(EG(ini_directives), "error_reporting", sizeof("error_reporting"), (void **) &EG(error_reporting_ini_entry)) == FAILURE)) { + break; + } + } + if (!EG(error_reporting_ini_entry)->modified) { + if (!EG(modified_ini_directives)) { + ALLOC_HASHTABLE(EG(modified_ini_directives)); + zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0); + } + if (EXPECTED(zend_hash_add(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting"), &EG(error_reporting_ini_entry), sizeof(zend_ini_entry*), NULL) == SUCCESS)) { + EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value; + EG(error_reporting_ini_entry)->orig_value_length = EG(error_reporting_ini_entry)->value_length; + EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable; + EG(error_reporting_ini_entry)->modified = 1; + } + } else if (EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value) { + efree(EG(error_reporting_ini_entry)->value); + } + EG(error_reporting_ini_entry)->value = estrndup("0", sizeof("0")-1); + EG(error_reporting_ini_entry)->value_length = sizeof("0")-1; + } while (0); } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6898,9 +6921,18 @@ static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ if (!EG(error_reporting) && Z_LVAL(EX_T(opline->op1.var).tmp_var) != 0) { Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL(EX_T(opline->op1.var).tmp_var); + EG(error_reporting) = Z_LVAL(restored_error_reporting); convert_to_string(&restored_error_reporting); - zend_alter_ini_entry_ex("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME, 1 TSRMLS_CC); - zendi_zval_dtor(restored_error_reporting); + if (EXPECTED(EG(error_reporting_ini_entry) != NULL)) { + if (EXPECTED(EG(error_reporting_ini_entry)->modified && + EG(error_reporting_ini_entry)->value != EG(error_reporting_ini_entry)->orig_value)) { + efree(EG(error_reporting_ini_entry)->value); + } + EG(error_reporting_ini_entry)->value = Z_STRVAL(restored_error_reporting); + EG(error_reporting_ini_entry)->value_length = Z_STRLEN(restored_error_reporting); + } else { + zendi_zval_dtor(restored_error_reporting); + } } if (EX(old_error_reporting) == &EX_T(opline->op1.var).tmp_var) { EX(old_error_reporting) = NULL; -- 2.40.0