com php-src: Use runtime-cache to avoid hash lookups in BIND_GLOBAL instruction: Zend/zend_compile.c Zend /zend_vm_def.h Zend/zend_vm_execute.h
ext/opcac he/Optimizer/compact_literals.c
| From: | Dmitry Stogov | Date: | Tue, 16 Sep 2014 20:52:45 +0000 |
| Subject: | com php-src: Use runtime-cache to avoid hash lookups in BIND_GLOBAL instruction: Zend/zend_compile.c Zend /zend_vm_def.h Zend/zend_vm_execute.h ext/opcac he/Optimizer/compact_literals.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-81701@lists.php.net to get a copy of this message | ||
Commit: 551ee4165b62ff6dbd32ce0dcc213d66fc8ae083
Author: Dmitry Stogov <dmitry@zend.com> Wed, 17 Sep 2014 00:52:45 +0400
Parents: c2decc6afc594ef67bc8f21e0f8d79a8236b000e
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=551ee4165b62ff6dbd32ce0dcc213d66fc8ae083
Log:
Use runtime-cache to avoid hash lookups in BIND_GLOBAL instruction
Changed paths:
M Zend/zend_compile.c
M Zend/zend_vm_def.h
M Zend/zend_vm_execute.h
M ext/opcache/Optimizer/compact_literals.c
Diff:
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 0f91a81..df44138 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -4586,7 +4586,8 @@ void zend_compile_global_var(zend_ast *ast TSRMLS_DC) /* {{{ */
}
if (zend_try_compile_cv(&result, var_ast TSRMLS_CC) == SUCCESS) {
- zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node TSRMLS_CC);
+ zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node TSRMLS_CC);
+ zend_alloc_cache_slot(opline->op2.constant TSRMLS_CC);
} else {
zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL TSRMLS_CC);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index c591b9b..ac015ae 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5891,19 +5891,46 @@ ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
zval *varname;
zval *value;
zval *variable_ptr;
- zend_string *name;
+ Bucket *p;
+ uint32_t idx;
SAVE_OPLINE();
varname = GET_OP2_ZVAL_PTR(BP_VAR_R);
- name = Z_STR_P(varname);
- value = zend_hash_find(&EG(symbol_table).ht, name);
- if (value == NULL) {
- value = zend_hash_add_new(&EG(symbol_table).ht, name, &EG(uninitialized_zval));
+ idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname));
+ /* index 0 can't be cached (NULL is a mark of uninitialized cache slot) */
+ p = EG(symbol_table).ht.arData + idx;
+ if (EXPECTED(idx > 0) &&
+ EXPECTED(idx < EG(symbol_table).ht.nNumUsed) &&
+ EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
+ (EXPECTED(p->key == Z_STR_P(varname)) ||
+ (EXPECTED(p->h == Z_STR_P(varname)->h) &&
+ EXPECTED(p->key != NULL) &&
+ EXPECTED(p->key->len == Z_STRLEN_P(varname)) &&
+ EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) {
+ value = &EG(symbol_table).ht.arData[idx].val;
/* GLOBAL variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(value) == IS_INDIRECT) {
- value = Z_INDIRECT_P(value);
- if (Z_TYPE_P(value) == IS_UNDEF) {
- ZVAL_NULL(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ ZVAL_NULL(value);
+ }
+ }
+ } else {
+ value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname));
+ if (UNEXPECTED(value == NULL)) {
+ value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname),
&EG(uninitialized_zval));
+ idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
+ CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)idx);
+ } else {
+ idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
+ CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)idx);
+ /* GLOBAL variable may be an INDIRECT pointer to CV */
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ ZVAL_NULL(value);
+ }
+ }
}
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index fb24560..d2afba6 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -36402,19 +36402,46 @@ static int ZEND_FASTCALL
ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN
zval *varname;
zval *value;
zval *variable_ptr;
- zend_string *name;
+ Bucket *p;
+ uint32_t idx;
SAVE_OPLINE();
varname = opline->op2.zv;
- name = Z_STR_P(varname);
- value = zend_hash_find(&EG(symbol_table).ht, name);
- if (value == NULL) {
- value = zend_hash_add_new(&EG(symbol_table).ht, name, &EG(uninitialized_zval));
+ idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname));
+ /* index 0 can't be cached (NULL is a mark of uninitialized cache slot) */
+ p = EG(symbol_table).ht.arData + idx;
+ if (EXPECTED(idx > 0) &&
+ EXPECTED(idx < EG(symbol_table).ht.nNumUsed) &&
+ EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
+ (EXPECTED(p->key == Z_STR_P(varname)) ||
+ (EXPECTED(p->h == Z_STR_P(varname)->h) &&
+ EXPECTED(p->key != NULL) &&
+ EXPECTED(p->key->len == Z_STRLEN_P(varname)) &&
+ EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) {
+ value = &EG(symbol_table).ht.arData[idx].val;
/* GLOBAL variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(value) == IS_INDIRECT) {
- value = Z_INDIRECT_P(value);
- if (Z_TYPE_P(value) == IS_UNDEF) {
- ZVAL_NULL(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ ZVAL_NULL(value);
+ }
+ }
+ } else {
+ value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname));
+ if (UNEXPECTED(value == NULL)) {
+ value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname),
&EG(uninitialized_zval));
+ idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
+ CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)idx);
+ } else {
+ idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
+ CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)idx);
+ /* GLOBAL variable may be an INDIRECT pointer to CV */
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
+ value = Z_INDIRECT_P(value);
+ if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ ZVAL_NULL(value);
+ }
+ }
}
}
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index 28e7a11..091437e 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -40,6 +40,7 @@
#define LITERAL_STATIC_PROPERTY 0x0700
#define LITERAL_METHOD 0x0800
#define LITERAL_PROPERTY 0x0900
+#define LITERAL_GLOBAL 0x0A00
#define LITERAL_EX_CLASS 0x4000
#define LITERAL_EX_OBJ 0x2000
@@ -278,6 +279,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
}
}
break;
+ case ZEND_BIND_GLOBAL:
+ LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1);
+ break;
default:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);