summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2010-04-22 15:03:17 +0000
committerDmitry Stogov <dmitry@php.net>2010-04-22 15:03:17 +0000
commite87d72002b7b173331c073e1e581e69f788d8a9c (patch)
tree73dbd1c9da527977364d580cf9af3e91e06e3e46 /Zend
parentac181e07efdf46c856033d9013b9bec5fb6cfe72 (diff)
downloadphp-git-e87d72002b7b173331c073e1e581e69f788d8a9c.tar.gz
Optimized access to global constants using values with pre-calculated hash_values from litersls table
Diffstat (limited to 'Zend')
-rw-r--r--Zend/micro_bench.php10
-rw-r--r--Zend/zend.h11
-rw-r--r--Zend/zend_compile.c84
-rw-r--r--Zend/zend_constants.c84
-rw-r--r--Zend/zend_constants.h1
-rw-r--r--Zend/zend_vm_def.h2
-rw-r--r--Zend/zend_vm_execute.h6
7 files changed, 162 insertions, 36 deletions
diff --git a/Zend/micro_bench.php b/Zend/micro_bench.php
index e07ee88ce5..0d705e942b 100644
--- a/Zend/micro_bench.php
+++ b/Zend/micro_bench.php
@@ -166,6 +166,14 @@ function create_object($n) {
}
}
+define('TEST', null);
+
+function read_const($n) {
+ for ($i = 0; $i < $n; ++$i) {
+ $x = TEST;
+ }
+}
+
/*****/
function empty_loop($n) {
@@ -272,4 +280,6 @@ $x->read_const(N);
$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");
diff --git a/Zend/zend.h b/Zend/zend.h
index 8aafd2cf81..7efa9f4825 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -525,11 +525,12 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#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)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index c523a3dfa0..9909643795 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -420,6 +420,76 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
}
/* }}} */
+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 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
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;
}
}
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 1743ffd2a8..f581842698 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -222,6 +222,31 @@ ZEND_API void zend_register_string_constant(const char *name, uint name_len, cha
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)
{
@@ -237,29 +262,7 @@ ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSR
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 @@ finish:
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;
diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h
index 75fb67e2eb..e8fb3f2116 100644
--- a/Zend/zend_constants.h
+++ b/Zend/zend_constants.h
@@ -69,6 +69,7 @@ ZEND_API void zend_register_stringl_constant(const char *name, uint name_len, ch
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
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b9e718fced..953f58a74c 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3329,7 +3329,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
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) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index e6e4f90cde..e48b807eea 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -2981,7 +2981,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
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 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
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 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
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) {