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

Reply via email to