]> granicus.if.org Git - php/commitdiff
Support for class constants and static members for internal classes
authorDmitry Stogov <dmitry@php.net>
Thu, 1 Sep 2005 10:05:01 +0000 (10:05 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 1 Sep 2005 10:05:01 +0000 (10:05 +0000)
NEWS
Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_object_handlers.c
Zend/zend_opcode.c
Zend/zend_reflection_api.c
ext/reflection/php_reflection.c

diff --git a/NEWS b/NEWS
index eb7f6af8423be456bf549ae97b73d1a136890500..c881bce6a71eeea032891bd63beb99bede765adc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? ????, PHP 6.0
+- Implemented support for class constants and static members for internal
+  classes (Dmitry, Michael Wallner)
 - Unicode support. (Andrei, Dmitriy, et al)
 - Changed "instanceof" operator, is_a() and is_subclass_of() functions to not
   call __autoload(). (Dmitry)
index 644ed615b80086d2377bdc98584827d355b0a523..b5ae4e46aa11105e0c4439ea91b279c3cf51345d 100644 (file)
@@ -838,7 +838,6 @@ static void const_to_unicode(zend_constant *c)
 static void class_to_unicode(zend_class_entry **ce)
 {
        zend_class_entry *new_ce = malloc(sizeof(zend_class_entry));
-       zend_constant tmp_const;
        zend_property_info tmp_info;
        zval* tmp_zval;
 
@@ -884,10 +883,36 @@ static void class_to_unicode(zend_class_entry **ce)
        zend_u_hash_init_ex(&new_ce->default_properties, (*ce)->default_properties.nNumOfElements, NULL, (*ce)->default_properties.pDestructor, 1, 1, 0);
        zend_hash_copy(&new_ce->default_properties, &(*ce)->default_properties, (copy_ctor_func_t) zval_ptr_to_unicode, &tmp_zval, sizeof(zval*));
 
-       if (new_ce->static_members) {
-               new_ce->static_members = (HashTable*)malloc(sizeof(HashTable));
-               zend_u_hash_init_ex(new_ce->static_members, (*ce)->static_members->nNumOfElements, NULL, (*ce)->static_members->pDestructor, 1, 1, 0);
-               zend_hash_copy(new_ce->static_members, (*ce)->static_members, (copy_ctor_func_t) zval_ptr_to_unicode, &tmp_zval, sizeof(zval*));
+       zend_u_hash_init_ex(&new_ce->default_static_members, (*ce)->default_static_members.nNumOfElements, NULL, (*ce)->default_static_members.pDestructor, 1, 1, 0);
+
+       {
+               HashPosition pos;
+               zval **p;
+
+               zend_hash_internal_pointer_reset_ex(&(*ce)->default_static_members, &pos);
+               while (zend_hash_get_current_data_ex(&(*ce)->default_static_members, (void**)&p, &pos) == SUCCESS) {
+                       char *str_index;
+                       uint str_length;
+                       ulong num_index;
+                       zval **q;
+
+                       zend_hash_get_current_key_ex(&(*ce)->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
+                       if ((*p)->is_ref &&
+                           (*ce)->parent &&
+                           zend_hash_find(&(*ce)->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
+                           *p == *q &&
+                           zend_hash_find(&new_ce->parent->u_twin->default_static_members, str_index, str_length, (void**)&q) == SUCCESS) {
+                               (*q)->refcount++;
+                               (*q)->is_ref = 1;
+                               zend_hash_add(&new_ce->default_static_members, str_index, str_length, (void**)q, sizeof(zval*), NULL);
+                       } else {
+                               zval *q = *p;
+                               zval_ptr_to_unicode(&q);
+                               q->is_ref = 0;
+                               zend_hash_add(&new_ce->default_static_members, str_index, str_length, (void**)&q, sizeof(zval*), NULL);
+                       }
+                       zend_hash_move_forward_ex(&(*ce)->default_static_members, &pos);
+               }
        }
 
        *ce = new_ce;
index 5d243b12994ae7f69cd0f1df5b342a2493f87fff..2590398467c2834a88cc12467a527890a3e4acbf 100644 (file)
@@ -347,6 +347,7 @@ struct _zend_class_entry {
        HashTable function_table;
        HashTable default_properties;
        HashTable properties_info;
+       HashTable default_static_members;
        HashTable *static_members;
        HashTable constants_table;
        struct _zend_function_entry *builtin_functions;
index 0b54bae3d133e478eebb322d32a08e2ff8895946..7fd4ba8496005aefafb204562242dad4b39f0a3a 100644 (file)
@@ -1076,13 +1076,65 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
 
 ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC)
 {
-       if (!class_type->constants_updated) {
+       if (!class_type->constants_updated || !class_type->static_members) {
                zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
                zend_class_entry *old_scope = *scope;
 
                *scope = class_type;
                zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
+
+               if (!class_type->static_members) {
+                       HashPosition pos;
+                       zval **p;
+
+                       if (class_type->parent) {
+                               zend_update_class_constants(class_type->parent TSRMLS_CC);
+                       }
+                       ALLOC_HASHTABLE(class_type->static_members);
+                       zend_u_hash_init(class_type->static_members, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
+
+                       zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
+                       while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
+                               char *str_index;
+                               uint str_length;
+                               ulong num_index;
+                               zend_uchar utype;
+                               zval **q;
+
+                               switch (zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos)) {
+                                       case HASH_KEY_IS_UNICODE:
+                                               utype = IS_UNICODE;
+                                               break;
+                                       case HASH_KEY_IS_BINARY:
+                                               utype = IS_BINARY;
+                                               break;
+                                       case HASH_KEY_IS_STRING:
+                                       default:
+                                               utype = IS_STRING;
+                                               break;
+                               }
+                               if ((*p)->is_ref &&
+                                   class_type->parent &&
+                                   zend_u_hash_find(&class_type->parent->default_static_members, utype, str_index, str_length, (void**)&q) == SUCCESS &&
+                                   *p == *q &&
+                                   zend_u_hash_find(class_type->parent->static_members, utype, str_index, str_length, (void**)&q) == SUCCESS) {
+                                       (*q)->refcount++;
+                                       (*q)->is_ref = 1;
+                                       zend_u_hash_add(class_type->static_members, utype, str_index, str_length, (void**)q, sizeof(zval*), NULL);
+                               } else {
+                                       zval *q;
+                                       
+                                       ALLOC_ZVAL(q);
+                                       *q = **p;
+                                       INIT_PZVAL(q)
+                                       zval_copy_ctor(q);
+                                       zend_u_hash_add(class_type->static_members, utype, str_index, str_length, (void**)&q, sizeof(zval*), NULL);
+                               }
+                               zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
+                       }
+               }
                zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
+               
                *scope = old_scope;
                class_type->constants_updated = 1;
        }
@@ -2749,7 +2801,7 @@ ZEND_API int zend_u_declare_property_ex(zend_class_entry *ce, zend_uchar type, v
                access_type |= ZEND_ACC_PUBLIC;
        }
        if (access_type & ZEND_ACC_STATIC) {
-               target_symbol_table = ce->static_members;
+               target_symbol_table = &ce->default_static_members;
        } else {
                target_symbol_table = &ce->default_properties;
        }
@@ -2914,6 +2966,73 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int
        return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
 }
 
+ZEND_API int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_length, zval *value TSRMLS_DC)
+{
+       return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL);
+}
+
+ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_length, long value TSRMLS_DC)
+{
+       zval *constant;
+
+       if (ce->type & ZEND_INTERNAL_CLASS) {
+               constant = malloc(sizeof(zval));
+       } else {
+               ALLOC_ZVAL(constant);
+       }
+       ZVAL_LONG(constant, value);
+       INIT_PZVAL(constant);
+       return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_length, zend_bool value TSRMLS_DC)
+{
+       zval *constant;
+
+       if (ce->type & ZEND_INTERNAL_CLASS) {
+               constant = malloc(sizeof(zval));
+       } else {
+               ALLOC_ZVAL(constant);
+       }
+       ZVAL_BOOL(constant, value);
+       INIT_PZVAL(constant);
+       return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_length, double value TSRMLS_DC)
+{
+       zval *constant;
+
+       if (ce->type & ZEND_INTERNAL_CLASS) {
+               constant = malloc(sizeof(zval));
+       } else {
+               ALLOC_ZVAL(constant);
+       }
+       ZVAL_DOUBLE(constant, value);
+       INIT_PZVAL(constant);
+       return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_length, char *value, size_t value_length TSRMLS_DC)
+{
+       zval *constant;
+
+       if (ce->type & ZEND_INTERNAL_CLASS) {
+               constant = malloc(sizeof(zval));
+               ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
+       } else {
+               ALLOC_ZVAL(constant);
+               ZVAL_STRINGL(constant, value, value_length, 1);
+       }
+       INIT_PZVAL(constant);
+       return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_length, char *value TSRMLS_DC)
+{
+       return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
+}
+
 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC)
 {
        zval property;
@@ -3067,6 +3186,172 @@ ZEND_API void zend_update_property_unicodel(zend_class_entry *scope, zval *objec
        zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
 }
 
+ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC)
+{
+       zval **property;
+       zend_class_entry *old_scope = EG(scope);
+       
+       EG(scope) = scope;
+       property = zend_std_get_static_property(scope, IS_STRING, name, name_length, 0 TSRMLS_CC);
+       EG(scope) = old_scope;
+       if (!property) {
+               return FAILURE;
+       } else {
+               if (*property != value) {
+                       if (PZVAL_IS_REF(*property)) {
+                               zval_dtor(*property);
+                               (*property)->type = value->type;
+                               (*property)->value = value->value;
+                               if (value->refcount > 0) {
+                                       zval_copy_ctor(*property);
+                               }
+                       } else {
+                               zval *garbage = *property;
+
+                               value->refcount++;
+                               if (PZVAL_IS_REF(value)) {
+                                       SEPARATE_ZVAL(&value);
+                               }
+                               *property = value;
+                               zval_ptr_dtor(&garbage);
+                       }
+               }
+               return SUCCESS;
+       }
+}
+
+ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC)
+{
+       zval *tmp;
+
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_NULL(tmp);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_BOOL(tmp, value);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_LONG(tmp, value);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_DOUBLE(tmp, value);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_STRING(tmp, value, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_len TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_STRINGL(tmp, value, value_len, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_ascii_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_ASCII_STRING(tmp, value, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_ascii_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_len TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_ASCII_STRINGL(tmp, value, value_len, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_rt_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_RT_STRING(tmp, value, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_rt_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_len TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_RT_STRINGL(tmp, value, value_len, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_unicode(zend_class_entry *scope, char *name, int name_length, UChar *value TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_UNICODE(tmp, value, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
+ZEND_API int zend_update_static_property_unicodel(zend_class_entry *scope, char *name, int name_length, UChar *value, int value_len TSRMLS_DC)
+{
+       zval *tmp;
+       
+       ALLOC_ZVAL(tmp);
+       tmp->is_ref = 0;
+       tmp->refcount = 0;
+       ZVAL_UNICODEL(tmp, value, value_len, 1);
+       return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
+}
+
 ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC)
 {
        zval property, *value;
@@ -3088,6 +3373,18 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
        return value;
 }
 
+ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC)
+{
+       zval **property;
+       zend_class_entry *old_scope = EG(scope);
+       
+       EG(scope) = scope;
+       property = zend_std_get_static_property(scope, IS_STRING, name, name_length, silent TSRMLS_CC);
+       EG(scope) = old_scope;
+
+       return property?*property:NULL;
+}
+
 /*
  * Return the string type that all the passed in types should be converted to.
  * If none of the types are string types, IS_UNICODE or IS_STRING is returned,
index f1190c5b23c1e72d483ce9a74f8af4a2031b712b..e265d56812dfe670f5b741a28d8c68a4dd9d1884 100644 (file)
@@ -220,6 +220,13 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int
 ZEND_API int zend_u_declare_property(zend_class_entry *ce, zend_uchar type, void *name, int name_length, zval *property, int access_type TSRMLS_DC);
 ZEND_API int zend_u_declare_property_ex(zend_class_entry *ce, zend_uchar type, void *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC);
 
+ZEND_API int zend_declare_class_constant(zend_class_entry *ce, char *name, size_t name_length, zval *value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, char *name, size_t name_length, long value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, char *name, size_t name_length, zend_bool value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, char *name, size_t name_length, double value TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, char *name, size_t name_length, char *value, size_t value_length TSRMLS_DC);
+ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, char *name, size_t name_length, char *value TSRMLS_DC);
+
 ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC);
 ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC);
@@ -235,8 +242,24 @@ ZEND_API void zend_update_property_rt_stringl(zend_class_entry *scope, zval *obj
 ZEND_API void zend_update_property_unicode(zend_class_entry *scope, zval *object, char *name, int name_length, UChar *value TSRMLS_DC);
 ZEND_API void zend_update_property_unicodel(zend_class_entry *scope, zval *object, char *name, int name_length, UChar *value, int value_length TSRMLS_DC);
 
+ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC);
+ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC);
+ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_ascii_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_ascii_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_rt_string(zend_class_entry *scope, char *name, int name_length, char *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_rt_stringl(zend_class_entry *scope, char *name, int name_length, char *value, int value_length TSRMLS_DC);
+ZEND_API int zend_update_static_property_unicode(zend_class_entry *scope, char *name, int name_length, UChar *value TSRMLS_DC);
+ZEND_API int zend_update_static_property_unicodel(zend_class_entry *scope, char *name, int name_length, UChar *value, int value_length TSRMLS_DC);
+
 ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC);
 
+ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC);
+
 ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC);
 ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC);
 ZEND_API zend_uchar zend_get_unified_string_type(int num_args TSRMLS_DC, ...);
index 38c22ea33883a018a781b65fc41cb7b2a4744b61..0dd3be64e453ed2816252429d02826dbbcd2a150 100644 (file)
@@ -788,6 +788,7 @@ ZEND_FUNCTION(get_class_vars)
        } else {
                array_init(return_value);
                add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC);
+               zend_update_class_constants(*pce TSRMLS_CC);
                add_class_vars(*pce, (*pce)->static_members, return_value TSRMLS_CC);
        }
 }
index 0549b51ef53993fbdb9363de22dfa91fd5bed801..2c078284c29e5e9e4861ec9cfeebd47f51832d02 100644 (file)
@@ -2123,9 +2123,17 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
                        zend_u_mangle_property_name(&prot_name, &prot_name_length, utype, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
                        if (child_info->flags & ZEND_ACC_STATIC) {
                                zval **prop;
-                               if (zend_u_hash_find(parent_ce->static_members, utype, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
+                               HashTable *ht;
+
+                               if (parent_ce->type != ce->type) {
+                                       /* User class extends internal class */
+                                       ht = parent_ce->static_members;
+                               } else {
+                                       ht = &parent_ce->default_static_members;
+                               }
+                               if (zend_u_hash_find(ht, utype, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
                                        zval **new_prop;
-                                       if (zend_u_hash_find(ce->static_members, utype, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
+                                       if (zend_u_hash_find(ht, utype, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
                                                if (Z_TYPE_PP(new_prop) != IS_NULL && Z_TYPE_PP(prop) != IS_NULL) {
                                                        char *prop_name, *tmp;
 
@@ -2135,8 +2143,8 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
                                                }
                                        }
                                        (*prop)->refcount++;
-                                       zend_u_hash_update(ce->static_members, utype, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
-                                       zend_u_hash_del(ce->static_members, utype, prot_name, prot_name_length+1);
+                                       zend_u_hash_update(&ce->default_static_members, utype, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
+                                       zend_u_hash_del(&ce->default_static_members, utype, prot_name, prot_name_length+1);
                                }
                        } else {
                                zend_u_hash_del(&ce->default_properties, utype, prot_name, prot_name_length+1);
@@ -2222,7 +2230,13 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
 
        /* Inherit properties */
        zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
-       zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0);
+       if (parent_ce->type != ce->type) {
+               /* User class extends internal class */
+               zend_update_class_constants(parent_ce  TSRMLS_CC);
+               zend_hash_merge(&ce->default_static_members, parent_ce->static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0);
+       } else {
+               zend_hash_merge(&ce->default_static_members, &parent_ce->default_static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0);
+       }
        zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
 
        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
@@ -2360,7 +2374,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
                zend_hash_destroy(&ce->function_table);
                zend_hash_destroy(&ce->default_properties);
                zend_hash_destroy(&ce->properties_info);
-               zend_hash_destroy(ce->static_members);
+               zend_hash_destroy(&ce->default_static_members);
                zend_hash_destroy(&ce->constants_table);
                return NULL;
        }
@@ -4110,17 +4124,12 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
 
        zend_u_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
        zend_u_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, UG(unicode), 0);
-
-       if (persistent_hashes) {
-               ce->static_members = (HashTable *) malloc(sizeof(HashTable));
-       } else {
-               ALLOC_HASHTABLE(ce->static_members);
-       }
-
-       zend_u_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+       zend_u_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
        zend_u_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
        zend_u_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, UG(unicode), 0);
 
+       ce->static_members = (ce->type == ZEND_INTERNAL_CLASS) ? NULL : &ce->default_static_members;
+
        if (nullify_handlers) {
                ce->constructor = NULL;
                ce->destructor = NULL;
index 6a14c72fc56e21f0048db5349ed2c1b2ab6a8fb5..bf8fec3c20cade9040fbc2de977de50784e5afa7 100644 (file)
@@ -838,7 +838,9 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, zend_uchar ty
                return NULL;
        }
 
-       zend_u_hash_quick_find(tmp_ce->static_members, type, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
+       zend_update_class_constants(tmp_ce TSRMLS_CC);
+
+       zend_u_hash_quick_find(tmp_ce->static_members, UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
 
        if (!retval) {
                if (silent) {
@@ -848,7 +850,6 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, zend_uchar ty
                }
        }
        
-       zval_update_constant(retval, (void *) 1 TSRMLS_CC);
        return retval;
 }
 
index b2e7a53bf3cae5faceec18292950d3d5dd58ec06..ff46517a7475f6417e14e9412e12f06106dc7da2 100644 (file)
@@ -141,11 +141,17 @@ ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC)
 
 ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
 {
+       if ((*pce)->static_members) {
+               if ((*pce)->static_members != &(*pce)->default_static_members) {
+                       zend_hash_destroy((*pce)->static_members);
+                       FREE_HASHTABLE((*pce)->static_members);
+               }
+               (*pce)->static_members = NULL;
+       }
        if ((*pce)->type == ZEND_USER_CLASS) {
                /* Clean all parts that can contain run-time data */
                /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
                   not contain objects and thus are not probelmatic */
-               zend_hash_clean((*pce)->static_members);
                zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
        }
        return 0;
@@ -162,10 +168,9 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                case ZEND_USER_CLASS:
                        zend_hash_destroy(&ce->default_properties);
                        zend_hash_destroy(&ce->properties_info);
-                       zend_hash_destroy(ce->static_members);
+                       zend_hash_destroy(&ce->default_static_members);
                        efree(ce->name);
                        zend_hash_destroy(&ce->function_table);
-                       FREE_HASHTABLE(ce->static_members);
                        zend_hash_destroy(&ce->constants_table);
                        if (ce->num_interfaces > 0 && ce->interfaces) {
                                efree(ce->interfaces);
@@ -178,10 +183,9 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                case ZEND_INTERNAL_CLASS:
                        zend_hash_destroy(&ce->default_properties);
                        zend_hash_destroy(&ce->properties_info);
-                       zend_hash_destroy(ce->static_members);
+                       zend_hash_destroy(&ce->default_static_members);
                        free(ce->name);
                        zend_hash_destroy(&ce->function_table);
-                       free(ce->static_members);
                        zend_hash_destroy(&ce->constants_table);
                        if (ce->num_interfaces > 0) {
                                free(ce->interfaces);
index faa9fcbf6a06b3978f47eeff8c2cac38f11504ba..970dceff73e5e646ce0f7bc6434836582693193a 100644 (file)
@@ -3566,6 +3566,7 @@ ZEND_METHOD(reflection_property, setValue)
                                return;
                        }
                }
+               zend_update_class_constants(intern->ce TSRMLS_CC);
                prop_table = intern->ce->static_members;
        } else {
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
index faa9fcbf6a06b3978f47eeff8c2cac38f11504ba..970dceff73e5e646ce0f7bc6434836582693193a 100644 (file)
@@ -3566,6 +3566,7 @@ ZEND_METHOD(reflection_property, setValue)
                                return;
                        }
                }
+               zend_update_class_constants(intern->ce TSRMLS_CC);
                prop_table = intern->ce->static_members;
        } else {
                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {