dmitry Thu, 22 Apr 2010 15:03:17 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=298322
Log: Optimized access to global constants using values with pre-calculated hash_values from litersls table Changed paths: U php/php-src/trunk/NEWS U php/php-src/trunk/Zend/micro_bench.php U php/php-src/trunk/Zend/zend.h U php/php-src/trunk/Zend/zend_compile.c U php/php-src/trunk/Zend/zend_constants.c U php/php-src/trunk/Zend/zend_constants.h U php/php-src/trunk/Zend/zend_vm_def.h U php/php-src/trunk/Zend/zend_vm_execute.h
Modified: php/php-src/trunk/NEWS =================================================================== --- php/php-src/trunk/NEWS 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/NEWS 2010-04-22 15:03:17 UTC (rev 298322) @@ -10,6 +10,8 @@ . ZEND_FETCH_DIM_? may fetch array and dimension operans in a different order . ZEND_RETURN is splitted into two new instructions ZEND_RETURN and ZEND_RETURN_BY_REF + . optimized access to global constants using values with pre-calculated + hash_values from litersls table - 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-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/micro_bench.php 2010-04-22 15:03:17 UTC (rev 298322) @@ -166,6 +166,14 @@ } } +define('TEST', null); + +function read_const($n) { + for ($i = 0; $i < $n; ++$i) { + $x = TEST; + } +} + /*****/ function empty_loop($n) { @@ -272,4 +280,6 @@ $t = end_test($t, '$x = Foo::TEST', $overhead); create_object(N); $t = end_test($t, 'new Foo()', $overhead); +read_const(N); +$t = end_test($t, '$x = TEST', $overhead); total($t0, "Total"); Modified: php/php-src/trunk/Zend/zend.h =================================================================== --- php/php-src/trunk/Zend/zend.h 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/zend.h 2010-04-22 15:03:17 UTC (rev 298322) @@ -525,11 +525,12 @@ #define IS_CONSTANT_ARRAY 9 /* Ugly hack to support constants as static array indices */ -#define IS_CONSTANT_TYPE_MASK 0x0f -#define IS_CONSTANT_UNQUALIFIED 0x10 -#define IS_CONSTANT_INDEX 0x80 -#define IS_LEXICAL_VAR 0x20 -#define IS_LEXICAL_REF 0x40 +#define IS_CONSTANT_TYPE_MASK 0x00f +#define IS_CONSTANT_UNQUALIFIED 0x010 +#define IS_CONSTANT_INDEX 0x080 +#define IS_LEXICAL_VAR 0x020 +#define IS_LEXICAL_REF 0x040 +#define IS_CONSTANT_IN_NAMESPACE 0x100 /* overloaded elements data types */ #define OE_IS_ARRAY (1<<0) Modified: php/php-src/trunk/Zend/zend_compile.c =================================================================== --- php/php-src/trunk/Zend/zend_compile.c 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/zend_compile.c 2010-04-22 15:03:17 UTC (rev 298322) @@ -420,6 +420,76 @@ } /* }}} */ +int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unqualified TSRMLS_DC) /* {{{ */ +{ + int ret, tmp_literal; + char *name, *tmp_name, *ns_separator; + int name_len, ns_len; + zval c; + + if (op_array->last_literal > 0 && + &op_array->literals[op_array->last_literal - 1].constant == zv) { + /* we already have function name as last literal (do nothing) */ + ret = op_array->last_literal - 1; + } else { + ret = zend_add_literal(op_array, zv); + } + + /* skip leading '\\' */ + if (Z_STRVAL_P(zv)[0] == '\\') { + name_len = Z_STRLEN_P(zv) - 1; + name = Z_STRVAL_P(zv) + 1; + } else { + name_len = Z_STRLEN_P(zv); + name = Z_STRVAL_P(zv); + } + ns_separator = zend_memrchr(name, '\\', name_len); + if (ns_separator) { + ns_len = ns_separator - name; + } else { + ns_len = 0; + } + + if (ns_len) { + /* lowercased namespace name & original constant name */ + tmp_name = estrndup(name, name_len); + zend_str_tolower(tmp_name, ns_len); + ZVAL_STRINGL(&c, tmp_name, name_len, 0); + tmp_literal = zend_add_literal(CG(active_op_array), &c); + CALCULATE_LITERAL_HASH(tmp_literal); + + /* lowercased namespace name & lowercased constant name */ + tmp_name = zend_str_tolower_dup(name, name_len); + ZVAL_STRINGL(&c, tmp_name, name_len, 0); + tmp_literal = zend_add_literal(CG(active_op_array), &c); + CALCULATE_LITERAL_HASH(tmp_literal); + } + + if (ns_len) { + if (!unqualified) { + return ret; + } + ns_len++; + name += ns_len; + name_len -= ns_len; + } + + /* original constant name */ + tmp_name = estrndup(name, name_len); + ZVAL_STRINGL(&c, tmp_name, name_len, 0); + tmp_literal = zend_add_literal(CG(active_op_array), &c); + CALCULATE_LITERAL_HASH(tmp_literal); + + /* lowercased constant name */ + tmp_name = zend_str_tolower_dup(name, name_len); + ZVAL_STRINGL(&c, tmp_name, name_len, 0); + tmp_literal = zend_add_literal(CG(active_op_array), &c); + CALCULATE_LITERAL_HASH(tmp_literal); + + return ret; +} +/* }}} */ + #define LITERAL_STRINGL(op, str, len, copy) do { \ zval _c; \ ZVAL_STRINGL(&_c, str, len, copy); \ @@ -4149,14 +4219,20 @@ opline->result.var = get_temporary_variable(CG(active_op_array)); GET_NODE(result, opline->result); SET_UNUSED(opline->op1); - if(compound) { + opline->op2_type = IS_CONST; + if (compound) { /* the name is unambiguous */ opline->extended_value = 0; - } else { + opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC); + } else { opline->extended_value = IS_CONSTANT_UNQUALIFIED; + if (CG(current_namespace)) { + opline->extended_value |= IS_CONSTANT_IN_NAMESPACE; + opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 1 TSRMLS_CC); + } else { + opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC); + } } - SET_NODE(opline->op2, constant_name); - CALCULATE_LITERAL_HASH(opline->op2.constant); break; } } Modified: php/php-src/trunk/Zend/zend_constants.c =================================================================== --- php/php-src/trunk/Zend/zend_constants.c 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/zend_constants.c 2010-04-22 15:03:17 UTC (rev 298322) @@ -222,7 +222,32 @@ zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC); } +static int zend_get_halt_offset_constant(const char *name, uint name_len, zend_constant **c TSRMLS_DC) +{ + int ret; + static char haltoff[] = "__COMPILER_HALT_OFFSET__"; + if (!EG(in_execution)) { + return 0; + } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 && + !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { + char *cfilename, *haltname; + int len, clen; + + cfilename = zend_get_executed_filename(TSRMLS_C); + clen = strlen(cfilename); + /* check for __COMPILER_HALT_OFFSET__ */ + zend_mangle_property_name(&haltname, &len, haltoff, + sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0); + ret = zend_hash_find(EG(zend_constants), haltname, len+1, (void **) c); + efree(haltname); + return (ret == SUCCESS); + } else { + return 0; + } +} + + ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC) { zend_constant *c; @@ -237,29 +262,7 @@ retval=0; } } else { - static char haltoff[] = "__COMPILER_HALT_OFFSET__"; - - if (!EG(in_execution)) { - retval = 0; - } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 && - !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { - char *cfilename, *haltname; - int len, clen; - - cfilename = zend_get_executed_filename(TSRMLS_C); - clen = strlen(cfilename); - /* check for __COMPILER_HALT_OFFSET__ */ - zend_mangle_property_name(&haltname, &len, haltoff, - sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0); - if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) { - retval = 1; - } else { - retval=0; - } - pefree(haltname, 0); - } else { - retval=0; - } + retval = zend_get_halt_offset_constant(name, name_len, &c TSRMLS_CC); } efree(lookup_name); } @@ -410,6 +413,41 @@ return zend_get_constant(name, name_len, result TSRMLS_CC); } +int zend_quick_get_constant(const zend_literal *key, zval *result, ulong flags TSRMLS_DC) +{ + zend_constant *c; + + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) { + key++; + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE || + (c->flags & CONST_CS) != 0) { + if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { + key++; + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) { + key++; + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE || + (c->flags & CONST_CS) != 0) { + + key--; + if (!zend_get_halt_offset_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { + return 0; + } + } + } + } else { + key--; + if (!zend_get_halt_offset_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { + return 0; + } + } + } + } + + INIT_PZVAL_COPY(result, &c->value); + zval_copy_ctor(result); + return 1; +} + ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC) { char *lowercase_name = NULL; Modified: php/php-src/trunk/Zend/zend_constants.h =================================================================== --- php/php-src/trunk/Zend/zend_constants.h 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/zend_constants.h 2010-04-22 15:03:17 UTC (rev 298322) @@ -69,6 +69,7 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC); void zend_copy_constants(HashTable *target, HashTable *sourc); void copy_zend_constant(zend_constant *c); +int zend_quick_get_constant(const zend_literal *key, zval *result, ulong flags TSRMLS_DC); END_EXTERN_C() #define ZEND_CONSTANT_DTOR (void (*)(void *)) free_zend_constant Modified: php/php-src/trunk/Zend/zend_vm_def.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_def.h 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/zend_vm_def.h 2010-04-22 15:03:17 UTC (rev 298322) @@ -3329,7 +3329,7 @@ SAVE_OPLINE(); if (OP1_TYPE == IS_UNUSED) { /* namespaced constant */ - if (!zend_get_constant_ex(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), &EX_T(opline->result.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) { + if (!zend_quick_get_constant(opline->op2.literal + 1, &EX_T(opline->result.var).tmp_var, opline->extended_value TSRMLS_CC)) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); if(!actual) { Modified: php/php-src/trunk/Zend/zend_vm_execute.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_execute.h 2010-04-22 14:24:49 UTC (rev 298321) +++ php/php-src/trunk/Zend/zend_vm_execute.h 2010-04-22 15:03:17 UTC (rev 298322) @@ -2981,7 +2981,7 @@ SAVE_OPLINE(); if (IS_CONST == IS_UNUSED) { /* namespaced constant */ - if (!zend_get_constant_ex(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), &EX_T(opline->result.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) { + if (!zend_quick_get_constant(opline->op2.literal + 1, &EX_T(opline->result.var).tmp_var, opline->extended_value TSRMLS_CC)) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); if(!actual) { @@ -11495,7 +11495,7 @@ SAVE_OPLINE(); if (IS_VAR == IS_UNUSED) { /* namespaced constant */ - if (!zend_get_constant_ex(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), &EX_T(opline->result.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) { + if (!zend_quick_get_constant(opline->op2.literal + 1, &EX_T(opline->result.var).tmp_var, opline->extended_value TSRMLS_CC)) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); if(!actual) { @@ -19381,7 +19381,7 @@ SAVE_OPLINE(); if (IS_UNUSED == IS_UNUSED) { /* namespaced constant */ - if (!zend_get_constant_ex(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), &EX_T(opline->result.var).tmp_var, NULL, opline->extended_value TSRMLS_CC)) { + if (!zend_quick_get_constant(opline->op2.literal + 1, &EX_T(opline->result.var).tmp_var, opline->extended_value TSRMLS_CC)) { if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) { char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv)); if(!actual) {
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php