From dbe66fb2cf1d413268e66117b5b9be489e1a5b5d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 13 Jan 2015 03:32:51 +0300 Subject: [PATCH] Improved access to static property. Now we cache pointers to zval instead of pointers to property_info. --- Zend/zend_object_handlers.c | 40 ++++---- Zend/zend_opcode.c | 20 ++-- Zend/zend_vm_def.h | 21 +++- Zend/zend_vm_execute.h | 189 ++++++++++++++++++++++++++++++++++-- 4 files changed, 229 insertions(+), 41 deletions(-) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index d018ea59ef..2cedb95f37 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1198,15 +1198,13 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *property_name, zend_bool silent, void **cache_slot) /* {{{ */ { zend_property_info *property_info; + zval *ret; - if (UNEXPECTED(cache_slot == NULL) || - (property_info = CACHED_POLYMORPHIC_PTR_EX(cache_slot, ce)) == NULL) { + if (cache_slot == NULL || + (ret = CACHED_POLYMORPHIC_PTR_EX(cache_slot, ce)) == NULL) { if (UNEXPECTED((property_info = zend_hash_find_ptr(&ce->properties_info, property_name)) == NULL)) { - if (!silent) { - zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, property_name->val); - } - return NULL; + goto undeclared_property; } if (UNEXPECTED(!zend_verify_property_access(property_info, ce))) { @@ -1217,28 +1215,32 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p } if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) { - if (!silent) { - zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, property_name->val); - } - return NULL; + goto undeclared_property; } zend_update_class_constants(ce); + ret = CE_STATIC_MEMBERS(ce) + property_info->offset; - if (EXPECTED(cache_slot != NULL)) { - CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, property_info); + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + goto undeclared_property; } - } - if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL) || - UNEXPECTED(Z_TYPE(CE_STATIC_MEMBERS(ce)[property_info->offset]) == IS_UNDEF)) { - if (!silent) { - zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, property_name->val); + if (EXPECTED(cache_slot != NULL)) { + CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, ret); + } + } else { + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { +undeclared_property: + if (!silent) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, property_name->val); + } + ret = NULL; } - return NULL; } - return &CE_STATIC_MEMBERS(ce)[property_info->offset]; + return ret; } /* }}} */ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 6e77716119..7b1232ab27 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -150,35 +150,31 @@ ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce) } ZEND_HASH_FOREACH_END(); } if (ce->static_members_table) { + zval *static_members = ce->static_members_table; int i; + ce->static_members_table = NULL; for (i = 0; i < ce->default_static_members_count; i++) { - if (Z_TYPE(ce->static_members_table[i]) != IS_UNDEF) { - zval tmp; - - ZVAL_COPY_VALUE(&tmp, &ce->static_members_table[i]); - ZVAL_UNDEF(&ce->static_members_table[i]); - zval_ptr_dtor(&tmp); - } + zval_ptr_dtor(&static_members[i]); } - ce->static_members_table = NULL; } } ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce) { if (CE_STATIC_MEMBERS(ce)) { + zval *static_members = CE_STATIC_MEMBERS(ce); int i; - for (i = 0; i < ce->default_static_members_count; i++) { - zval_ptr_dtor(&CE_STATIC_MEMBERS(ce)[i]); - } - efree(CE_STATIC_MEMBERS(ce)); #ifdef ZTS CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL; #else ce->static_members_table = NULL; #endif + for (i = 0; i < ce->default_static_members_count; i++) { + zval_ptr_dtor(&static_members[i]); + } + efree(static_members); } } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 808a3ff374..e733e1a517 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1112,7 +1112,26 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V zend_class_entry *ce; if (OP2_TYPE == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (OP1_TYPE == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index bc5eb60b31..678c90480a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3759,7 +3759,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type zend_class_entry *ce; if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (IS_CONST == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -5252,7 +5271,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, zend_class_entry *ce; if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (IS_CONST == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -5677,7 +5715,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ zend_class_entry *ce; if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (IS_CONST == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -25092,7 +25149,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z zend_class_entry *ce; if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (IS_CV == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -26916,7 +26992,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN zend_class_entry *ce; if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (IS_CV == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -27762,7 +27857,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, zend_class_entry *ce; if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if (IS_CV == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -33125,7 +33239,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(int typ zend_class_entry *ce; if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -33896,7 +34029,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(int type, zend_class_entry *ce; if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); @@ -34234,7 +34386,26 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int ty zend_class_entry *ce; if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + 1); + + /* check if static properties were destoyed */ + if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) { + zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val); + } + + if (type == BP_VAR_R || type == BP_VAR_IS) { + if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) { + ZVAL_UNREF(retval); + } + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } else { + ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); + } + ZEND_VM_NEXT_OPCODE(); + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); } else { ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0); -- 2.40.0