dmitry Thu, 08 Jul 2010 14:05:11 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=301081
Log: - use interned strings for auto globals - $GLOBALS became a JIT autoglobal, so it's initialized only if used (this may affect opcode caches) Changed paths: U php/php-src/trunk/NEWS U php/php-src/trunk/Zend/micro_bench.php U php/php-src/trunk/Zend/zend.c U php/php-src/trunk/Zend/zend_compile.c U php/php-src/trunk/Zend/zend_compile.h U php/php-src/trunk/Zend/zend_execute_API.c U php/php-src/trunk/ext/session/session.c U php/php-src/trunk/main/php_variables.c
Modified: php/php-src/trunk/NEWS =================================================================== --- php/php-src/trunk/NEWS 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/NEWS 2010-07-08 14:05:11 UTC (rev 301081) @@ -19,6 +19,8 @@ instruction without previous ZEND_FETCH_CLASS. . eliminated unnecessary iterations during request startup/shutdown . zend_stack initialization is delayed before the actual usage + . $GLOBALS became a JIT autoglobal, so it's initialized only if used + (this may affect opcode caches) - 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 Modified: php/php-src/trunk/Zend/micro_bench.php =================================================================== --- php/php-src/trunk/Zend/micro_bench.php 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/Zend/micro_bench.php 2010-07-08 14:05:11 UTC (rev 301081) @@ -174,6 +174,20 @@ } } +function read_auto_global($n) { + for ($i = 0; $i < $n; ++$i) { + $x = $_GET; + } +} + +$g_var = 0; + +function read_global_var($n) { + for ($i = 0; $i < $n; ++$i) { + $x = $GLOBALS['g_var']; + } +} + /*****/ function empty_loop($n) { @@ -282,4 +296,8 @@ $t = end_test($t, 'new Foo()', $overhead); read_const(N); $t = end_test($t, '$x = TEST', $overhead); +read_auto_global(N); +$t = end_test($t, '$x = $_GET', $overhead); +read_global_var(N); +$t = end_test($t, '$x = $GLOBALS[\'v\']', $overhead); total($t0, "Total"); Modified: php/php-src/trunk/Zend/zend.c =================================================================== --- php/php-src/trunk/Zend/zend.c 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/Zend/zend.c 2010-07-08 14:05:11 UTC (rev 301081) @@ -593,6 +593,20 @@ void zend_init_opcodes_handlers(void); +static zend_bool php_auto_globals_create_globals(char *name, uint name_len TSRMLS_DC) /* {{{ */ +{ + zval *globals; + + ALLOC_ZVAL(globals); + Z_SET_REFCOUNT_P(globals, 1); + Z_SET_ISREF_P(globals); + Z_TYPE_P(globals) = IS_ARRAY; + Z_ARRVAL_P(globals) = &EG(symbol_table); + zend_hash_update(&EG(symbol_table), name, name_len + 1, &globals, sizeof(zval *), NULL); + return 0; +} +/* }}} */ + int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC) /* {{{ */ { #ifdef ZTS @@ -660,7 +674,7 @@ zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0); - zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0); + zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0); zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0); zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0); @@ -701,7 +715,7 @@ zend_interned_strings_init(TSRMLS_C); zend_startup_builtin_functions(TSRMLS_C); zend_register_standard_constants(TSRMLS_C); - zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, NULL TSRMLS_CC); + zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, 1, php_auto_globals_create_globals TSRMLS_CC); #ifndef ZTS zend_init_rsrc_plist(TSRMLS_C); Modified: php/php-src/trunk/Zend/zend_compile.c =================================================================== --- php/php-src/trunk/Zend/zend_compile.c 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/Zend/zend_compile.c 2010-07-08 14:05:11 UTC (rev 301081) @@ -163,27 +163,6 @@ /* }}} */ -int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */ -{ - auto_global->armed = (auto_global->auto_global_callback ? 1 : 0); - return 0; -} -/* }}} */ - - -ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */ -{ - zend_auto_global *auto_global; - - if (zend_hash_find(CG(auto_globals), varname, varname_length+1, (void **) &auto_global)==FAILURE) { - return FAILURE; - } - auto_global->armed = 0; - return SUCCESS; -} -/* }}} */ - - static void init_compiler_declarables(TSRMLS_D) /* {{{ */ { Z_TYPE(CG(declarables).ticks) = IS_LONG; @@ -211,7 +190,6 @@ CG(has_bracketed_namespaces) = 0; CG(current_import) = NULL; init_compiler_declarables(TSRMLS_C); - zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC); zend_stack_init(&CG(labels_stack)); CG(labels) = NULL; @@ -6069,12 +6047,6 @@ } /* }}} */ -void zend_auto_global_dtor(zend_auto_global *auto_global) /* {{{ */ -{ - free(auto_global->name); -} -/* }}} */ - zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */ { zend_auto_global *auto_global; @@ -6089,18 +6061,38 @@ } /* }}} */ -int zend_register_auto_global(const char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */ +int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */ { zend_auto_global auto_global; - auto_global.name = zend_strndup(name, name_len); + auto_global.name = zend_new_interned_string(name, name_len + 1, 0); auto_global.name_len = name_len; auto_global.auto_global_callback = auto_global_callback; + auto_global.jit = jit; return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL); } /* }}} */ +static int zend_auto_global_init(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */ +{ + if (auto_global->jit) { + auto_global->armed = 1; + } else if (auto_global->auto_global_callback) { + auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC); + } else { + auto_global->armed = 0; + } + return 0; +} +/* }}} */ + +ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */ +{ + zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_init TSRMLS_CC); +} +/* }}} */ + int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */ { int retval; Modified: php/php-src/trunk/Zend/zend_compile.h =================================================================== --- php/php-src/trunk/Zend/zend_compile.h 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/Zend/zend_compile.h 2010-07-08 14:05:11 UTC (rev 301081) @@ -651,13 +651,13 @@ char *name; uint name_len; zend_auto_global_callback auto_global_callback; + zend_bool jit; zend_bool armed; } zend_auto_global; -void zend_auto_global_dtor(zend_auto_global *auto_global); -ZEND_API int zend_register_auto_global(const char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC); +ZEND_API int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC); +ZEND_API void zend_activate_auto_globals(TSRMLS_D); ZEND_API zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC); -ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC); ZEND_API size_t zend_dirname(char *path, size_t len); int zendlex(znode *zendlval TSRMLS_DC); Modified: php/php-src/trunk/Zend/zend_execute_API.c =================================================================== --- php/php-src/trunk/Zend/zend_execute_API.c 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/Zend/zend_execute_API.c 2010-07-08 14:05:11 UTC (rev 301081) @@ -159,16 +159,6 @@ zend_vm_stack_push((void *) NULL TSRMLS_CC); zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0); - { - zval *globals; - - ALLOC_ZVAL(globals); - Z_SET_REFCOUNT_P(globals, 1); - Z_SET_ISREF_P(globals); - Z_TYPE_P(globals) = IS_ARRAY; - Z_ARRVAL_P(globals) = &EG(symbol_table); - zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL); - } EG(active_symbol_table) = &EG(symbol_table); zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC); Modified: php/php-src/trunk/ext/session/session.c =================================================================== --- php/php-src/trunk/ext/session/session.c 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/ext/session/session.c 2010-07-08 14:05:11 UTC (rev 301081) @@ -1993,7 +1993,7 @@ static PHP_MINIT_FUNCTION(session) /* {{{ */ { - zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, NULL TSRMLS_CC); + zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, 0, NULL TSRMLS_CC); PS(module_number) = module_number; /* if we really need this var we need to init it in zts mode as well! */ Modified: php/php-src/trunk/main/php_variables.c =================================================================== --- php/php-src/trunk/main/php_variables.c 2010-07-08 13:59:53 UTC (rev 301080) +++ php/php-src/trunk/main/php_variables.c 2010-07-08 14:05:11 UTC (rev 301081) @@ -643,98 +643,106 @@ */ int php_hash_environment(TSRMLS_D) { - char *p; - unsigned char _gpc_flags[5] = {0, 0, 0, 0, 0}; - struct auto_global_record { - char *name; - uint name_len; - zend_bool jit_initialization; - } auto_global_records[] = { - { "_POST", sizeof("_POST"), 0 }, - { "_GET", sizeof("_GET"), 0 }, - { "_COOKIE", sizeof("_COOKIE"), 0 }, - { "_SERVER", sizeof("_SERVER"), 1 }, - { "_ENV", sizeof("_ENV"), 1 }, - { "_FILES", sizeof("_FILES"), 0 }, - }; - size_t num_track_vars = sizeof(auto_global_records)/sizeof(struct auto_global_record); - size_t i; - - /* jit_initialization = 0; */ - for (i=0; i<num_track_vars; i++) { - PG(http_globals)[i] = NULL; + memset(PG(http_globals), 0, sizeof(PG(http_globals))); + zend_activate_auto_globals(TSRMLS_C); + if (PG(register_argc_argv)) { + php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC); } + return SUCCESS; +} +/* }}} */ - for (p=PG(variables_order); p && *p; p++) { - switch(*p) { - case 'p': - case 'P': - if (!_gpc_flags[0] && !SG(headers_sent) && SG(request_info).request_method && !strcasecmp(SG(request_info).request_method, "POST")) { - sapi_module.treat_data(PARSE_POST, NULL, NULL TSRMLS_CC); /* POST Data */ - _gpc_flags[0] = 1; - } - break; - case 'c': - case 'C': - if (!_gpc_flags[1]) { - sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC); /* Cookie Data */ - _gpc_flags[1] = 1; - } - break; - case 'g': - case 'G': - if (!_gpc_flags[2]) { - sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC); /* GET Data */ - _gpc_flags[2] = 1; - } - break; - case 'e': - case 'E': - if (!PG(auto_globals_jit) && !_gpc_flags[3]) { - zend_auto_global_disable_jit("_ENV", sizeof("_ENV")-1 TSRMLS_CC); - php_auto_globals_create_env("_ENV", sizeof("_ENV")-1 TSRMLS_CC); - _gpc_flags[3] = 1; - } - break; - case 's': - case 'S': - if (!PG(auto_globals_jit) && !_gpc_flags[4]) { - zend_auto_global_disable_jit("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC); - php_register_server_variables(TSRMLS_C); - _gpc_flags[4] = 1; - } - break; +static zend_bool php_auto_globals_create_get(char *name, uint name_len TSRMLS_DC) +{ + zval *vars; + + if (PG(variables_order) && (strchr(PG(variables_order),'G') || strchr(PG(variables_order),'g'))) { + sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC); + vars = PG(http_globals)[TRACK_VARS_GET]; + } else { + ALLOC_ZVAL(vars); + array_init(vars); + INIT_PZVAL(vars); + if (PG(http_globals)[TRACK_VARS_GET]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]); } + PG(http_globals)[TRACK_VARS_GET] = vars; } - /* argv/argc support */ - if (PG(register_argc_argv)) { - php_build_argv(SG(request_info).query_string, PG(http_globals)[TRACK_VARS_SERVER] TSRMLS_CC); + zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); + Z_ADDREF_P(vars); + + return 0; /* don't rearm */ +} + +static zend_bool php_auto_globals_create_post(char *name, uint name_len TSRMLS_DC) +{ + zval *vars; + + if (PG(variables_order) && + (strchr(PG(variables_order),'P') || strchr(PG(variables_order),'p')) && + !SG(headers_sent) && + SG(request_info).request_method && + !strcasecmp(SG(request_info).request_method, "POST")) { + sapi_module.treat_data(PARSE_POST, NULL, NULL TSRMLS_CC); + vars = PG(http_globals)[TRACK_VARS_POST]; + } else { + ALLOC_ZVAL(vars); + array_init(vars); + INIT_PZVAL(vars); + if (PG(http_globals)[TRACK_VARS_POST]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]); + } + PG(http_globals)[TRACK_VARS_POST] = vars; } - for (i=0; i<num_track_vars; i++) { - if (PG(auto_globals_jit) && auto_global_records[i].jit_initialization) { - continue; + zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); + Z_ADDREF_P(vars); + + return 0; /* don't rearm */ +} + +static zend_bool php_auto_globals_create_cookie(char *name, uint name_len TSRMLS_DC) +{ + zval *vars; + + if (PG(variables_order) && (strchr(PG(variables_order),'C') || strchr(PG(variables_order),'c'))) { + sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC); + vars = PG(http_globals)[TRACK_VARS_COOKIE]; + } else { + ALLOC_ZVAL(vars); + array_init(vars); + INIT_PZVAL(vars); + if (PG(http_globals)[TRACK_VARS_COOKIE]) { + zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]); } - if (!PG(http_globals)[i]) { - ALLOC_ZVAL(PG(http_globals)[i]); - array_init(PG(http_globals)[i]); - INIT_PZVAL(PG(http_globals)[i]); - } - - Z_ADDREF_P(PG(http_globals)[i]); - zend_hash_update(&EG(symbol_table), auto_global_records[i].name, auto_global_records[i].name_len, &PG(http_globals)[i], sizeof(zval *), NULL); + PG(http_globals)[TRACK_VARS_COOKIE] = vars; } - /* Create _REQUEST */ - if (!PG(auto_globals_jit)) { - zend_auto_global_disable_jit("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC); - php_auto_globals_create_request("_REQUEST", sizeof("_REQUEST")-1 TSRMLS_CC); + zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); + Z_ADDREF_P(vars); + + return 0; /* don't rearm */ +} + +static zend_bool php_auto_globals_create_files(char *name, uint name_len TSRMLS_DC) +{ + zval *vars; + + if (PG(http_globals)[TRACK_VARS_FILES]) { + vars = PG(http_globals)[TRACK_VARS_FILES]; + } else { + ALLOC_ZVAL(vars); + array_init(vars); + INIT_PZVAL(vars); + PG(http_globals)[TRACK_VARS_FILES] = vars; } - return SUCCESS; + zend_hash_update(&EG(symbol_table), name, name_len + 1, &vars, sizeof(zval *), NULL); + Z_ADDREF_P(vars); + + return 0; /* don't rearm */ } -/* }}} */ static zend_bool php_auto_globals_create_server(char *name, uint name_len TSRMLS_DC) { @@ -837,19 +845,19 @@ } } - zend_hash_update(&EG(symbol_table), "_REQUEST", sizeof("_REQUEST"), &form_variables, sizeof(zval *), NULL); + zend_hash_update(&EG(symbol_table), name, name_len + 1, &form_variables, sizeof(zval *), NULL); return 0; } void php_startup_auto_globals(TSRMLS_D) { - zend_register_auto_global("_GET", sizeof("_GET")-1, NULL TSRMLS_CC); - zend_register_auto_global("_POST", sizeof("_POST")-1, NULL TSRMLS_CC); - zend_register_auto_global("_COOKIE", sizeof("_COOKIE")-1, NULL TSRMLS_CC); - zend_register_auto_global("_SERVER", sizeof("_SERVER")-1, php_auto_globals_create_server TSRMLS_CC); - zend_register_auto_global("_ENV", sizeof("_ENV")-1, php_auto_globals_create_env TSRMLS_CC); - zend_register_auto_global("_REQUEST", sizeof("_REQUEST")-1, php_auto_globals_create_request TSRMLS_CC); - zend_register_auto_global("_FILES", sizeof("_FILES")-1, NULL TSRMLS_CC); + zend_register_auto_global("_GET", sizeof("_GET")-1, 0, php_auto_globals_create_get TSRMLS_CC); + zend_register_auto_global("_POST", sizeof("_POST")-1, 0, php_auto_globals_create_post TSRMLS_CC); + zend_register_auto_global("_COOKIE", sizeof("_COOKIE")-1, 0, php_auto_globals_create_cookie TSRMLS_CC); + zend_register_auto_global("_SERVER", sizeof("_SERVER")-1, PG(auto_globals_jit), php_auto_globals_create_server TSRMLS_CC); + zend_register_auto_global("_ENV", sizeof("_ENV")-1, PG(auto_globals_jit), php_auto_globals_create_env TSRMLS_CC); + zend_register_auto_global("_REQUEST", sizeof("_REQUEST")-1, PG(auto_globals_jit), php_auto_globals_create_request TSRMLS_CC); + zend_register_auto_global("_FILES", sizeof("_FILES")-1, 0, php_auto_globals_create_files TSRMLS_CC); } /*
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php