summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_API.c74
-rw-r--r--Zend/zend_compile.c26
-rw-r--r--Zend/zend_vm_def.h4
-rw-r--r--Zend/zend_vm_execute.h48
-rw-r--r--ext/reflection/php_reflection.c2
5 files changed, 101 insertions, 53 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index de9db824a7..85cf32e32c 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1140,10 +1140,42 @@ static int zval_update_class_constant(zval *pp, int is_static, int offset TSRMLS
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
{
- if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
+ int i;
+
+ /* initialize static members of internal class */
+ if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
+ zval *p;
+
+ if (class_type->parent) {
+ zend_update_class_constants(class_type->parent TSRMLS_CC);
+ }
+#if ZTS
+ CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
+#else
+ class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
+#endif
+ for (i = 0; i < class_type->default_static_members_count; i++) {
+ p = &class_type->default_static_members_table[i];
+ if (Z_ISREF_P(p) &&
+ class_type->parent &&
+ i < class_type->parent->default_static_members_count &&
+ p == &class_type->parent->default_static_members_table[i] &&
+ Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
+ ) {
+ zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
+
+ ZVAL_NEW_REF(q, q);
+ ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
+ Z_ADDREF_P(q);
+ } else {
+ ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
+ }
+ }
+ }
+
+ if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0) {
zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
zend_class_entry *old_scope = *scope;
- int i;
zval *val;
*scope = class_type;
@@ -1158,36 +1190,6 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
}
}
- if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
- zval *p;
-
- if (class_type->parent) {
- zend_update_class_constants(class_type->parent TSRMLS_CC);
- }
-#if ZTS
- CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
-#else
- class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
-#endif
- for (i = 0; i < class_type->default_static_members_count; i++) {
- p = &class_type->default_static_members_table[i];
- if (Z_ISREF_P(p) &&
- class_type->parent &&
- i < class_type->parent->default_static_members_count &&
- p == &class_type->parent->default_static_members_table[i] &&
- Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
- ) {
- zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
-
- ZVAL_NEW_REF(q, q);
- ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
- Z_ADDREF_P(q);
- } else {
- ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
- }
- }
- }
-
for (i = 0; i < class_type->default_static_members_count; i++) {
zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i TSRMLS_CC);
}
@@ -2616,7 +2618,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
class_entry->type = ZEND_INTERNAL_CLASS;
zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
- class_entry->ce_flags = ce_flags;
+ class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
class_entry->info.internal.module = EG(current_module);
if (class_entry->info.internal.builtin_functions) {
@@ -3548,6 +3550,9 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
{
zend_property_info property_info, *property_info_ptr;
+ if (Z_CONSTANT_P(property)) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
if (!(access_type & ZEND_ACC_PPP_MASK)) {
access_type |= ZEND_ACC_PUBLIC;
}
@@ -3681,6 +3686,9 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *nam
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
{
+ if (Z_CONSTANT_P(value)) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
return zend_hash_str_update(&ce->constants_table, name, name_length, value) ?
SUCCESS : FAILURE;
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 910707bcb0..f950af6877 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3719,6 +3719,9 @@ static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_en
ZVAL_NEW_REF(zv, zv);
}
}
+ if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
if (zend_hash_add(&ce->constants_table, name, zv)) {
Z_ADDREF_P(zv);
}
@@ -3766,11 +3769,17 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
#ifdef ZTS
if (parent_ce->type != ce->type) {
ZVAL_DUP(&ce->default_properties_table[i], &parent_ce->default_properties_table[i]);
+ if (Z_OPT_CONSTANT(ce->default_properties_table[i])) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
continue;
}
#endif
ZVAL_COPY(&ce->default_properties_table[i], &parent_ce->default_properties_table[i]);
+ if (Z_OPT_CONSTANT(ce->default_properties_table[i])) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
}
ce->default_properties_count += parent_ce->default_properties_count;
}
@@ -3791,6 +3800,9 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
ZVAL_MAKE_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
Z_ADDREF(ce->default_static_members_table[i]);
+ if (Z_CONSTANT_P(Z_REFVAL(ce->default_static_members_table[i]))) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
}
ce->default_static_members_count += parent_ce->default_static_members_count;
ce->static_members_table = ce->default_static_members_table;
@@ -3809,6 +3821,9 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
ZVAL_MAKE_REF(&parent_ce->default_static_members_table[i]);
ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
Z_ADDREF(ce->default_static_members_table[i]);
+ if (Z_CONSTANT_P(Z_REFVAL(ce->default_static_members_table[i]))) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
}
ce->default_static_members_count += parent_ce->default_static_members_count;
if (ce->type == ZEND_USER_CLASS) {
@@ -5446,8 +5461,6 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty
void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC) /* {{{ */
{
- zval property;
-
if ((Z_TYPE(value->u.constant) == IS_ARRAY) ||
(Z_TYPE(value->u.constant) == IS_CONSTANT_AST &&
Z_ASTVAL(value->u.constant)->kind == ZEND_INIT_ARRAY)) {
@@ -5459,13 +5472,14 @@ void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC) /*
return;
}
- ZVAL_COPY_VALUE(&property, &value->u.constant);
-
Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC);
if (IS_INTERNED(Z_STR(var_name->u.constant))) {
Z_TYPE_FLAGS(var_name->u.constant) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
}
- if (zend_hash_add(&CG(active_class_entry)->constants_table, Z_STR(var_name->u.constant), &property) == NULL) {
+ if (Z_CONSTANT(value->u.constant)) {
+ CG(active_class_entry)->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
+ if (zend_hash_add(&CG(active_class_entry)->constants_table, Z_STR(var_name->u.constant), &value->u.constant) == NULL) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name->val, Z_STRVAL(var_name->u.constant));
}
FREE_PNODE(var_name);
@@ -6987,7 +7001,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
ce->refcount = 1;
- ce->ce_flags = 0;
+ ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
ce->default_properties_table = NULL;
ce->default_static_members_table = NULL;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 690a8269b9..38377d3cce 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1189,7 +1189,9 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
FREE_OP1();
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index e37cba17ae..b69dcbf711 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3684,7 +3684,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
}
@@ -5508,7 +5510,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
}
@@ -6218,7 +6222,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
}
@@ -8930,7 +8936,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_dtor(free_op1.var);
}
@@ -10615,7 +10623,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_dtor(free_op1.var);
}
@@ -11325,7 +11335,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_dtor(free_op1.var);
}
@@ -14826,7 +14838,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_ptr_dtor_nogc(free_op1.var);
}
@@ -19181,7 +19195,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_ptr_dtor_nogc(free_op1.var);
}
@@ -21070,7 +21086,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
zval_ptr_dtor_nogc(free_op1.var);
}
@@ -31798,7 +31816,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
}
@@ -35850,7 +35870,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
}
@@ -37621,7 +37643,9 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
}
}
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
- zval_update_constant(retval, 1 TSRMLS_CC);
+ if (Z_CONSTANT_P(retval)) {
+ zval_update_constant(retval, 1 TSRMLS_CC);
+ }
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
}
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 8611c9c8e2..678e328f68 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -4142,7 +4142,7 @@ ZEND_METHOD(reflection_class, getModifiers)
}
GET_REFLECTION_OBJECT_PTR(ce);
- RETURN_LONG(ce->ce_flags);
+ RETURN_LONG(ce->ce_flags & ~ZEND_ACC_CONSTANTS_UPDATED);
}
/* }}} */