Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:17756 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 43986 invoked by uid 1010); 9 Aug 2005 22:18:51 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 43971 invoked from network); 9 Aug 2005 22:18:51 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 9 Aug 2005 22:18:51 -0000 X-Host-Fingerprint: 62.46.17.23 M217P023.dipool.highway.telekom.at Received: from ([62.46.17.23:22805] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.0 beta r(6323M)) with SMTP id 4A/29-04646-ACB29F24 for ; Tue, 09 Aug 2005 18:18:50 -0400 Message-ID: <4A.29.04646.ACB29F24@pb1.pair.com> To: internals@lists.php.net Date: Wed, 10 Aug 2005 00:19:01 +0200 User-Agent: Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.6) Gecko/20040114 [ http://iworks.at ] X-Accept-Language: de-at, de, en-us, en MIME-Version: 1.0 References: <34.85.04646.D7C98F24@pb1.pair.com> <77.16.04646.4DF98F24@pb1.pair.com> <937135535.20050809205542@marcus-boerger.de> In-Reply-To: <937135535.20050809205542@marcus-boerger.de> Content-Type: multipart/mixed; boundary="------------030005060603000006060302" X-Posted-By: 62.46.17.23 Subject: Re: [PHP-DEV] Re: RFC: internal class' static properties From: mike@php.net (Michael Wallner) --------------030005060603000006060302 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Marcus Boerger schrieb: > regarding static props the solution is to define another hash table > in the class_entry that holdes the initial values for the static > variables. During minit these would be copied to the used hash table, > done. But even though the solution is pretty easy i do not know if we > really want to support that. We have default properties and all that > stuff already. I attached a patch, which fixes the static property issue for me, though I didn't test as a webserver module yet. > Can't we simply check if default values for static > properties wouldn't do the job and if there is something missing in > that? Huh? I even think that zend_std_get_static_property() is not enough... This forces you to have real zvals for your static properties. Maybe a minor issue (but still an issue :) > class consts should be easy and we two times had a patch for that. > And i definitively ask to support that since otherwise we flood our > namespace, see pdo, spl and the amount of defines there. With a peep > to pecl i see tons of more consts (especially in http). The patch also contains API for class constants, tough valgrind reports some odd errors about the constants_table (among "some" others...) Anyway, I'd be glad if the patch could be reviewed, fixed (as it's most probably not totally accurate) and -even partially- applied. Thanks, Michael --------------030005060603000006060302 Content-Type: text/plain; name="zend_static_properties.patch.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="zend_static_properties.patch.txt" Index: Zend/zend.h =================================================================== RCS file: /repository/ZendEngine2/zend.h,v retrieving revision 1.293 diff -u -r1.293 zend.h --- Zend/zend.h 3 Aug 2005 13:30:46 -0000 1.293 +++ Zend/zend.h 9 Aug 2005 21:56:06 -0000 @@ -331,7 +331,8 @@ HashTable function_table; HashTable default_properties; HashTable properties_info; - HashTable *static_members; + HashTable default_static_properties; + HashTable static_properties; HashTable constants_table; struct _zend_function_entry *builtin_functions; Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.296 diff -u -r1.296 zend_API.c --- Zend/zend_API.c 8 Aug 2005 14:25:05 -0000 1.296 +++ Zend/zend_API.c 9 Aug 2005 21:56:11 -0000 @@ -759,7 +759,7 @@ *scope = class_type; zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); - zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); + zend_hash_apply_with_argument(&class_type->default_static_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); *scope = old_scope; class_type->constants_updated = 1; } @@ -2126,7 +2126,7 @@ access_type |= ZEND_ACC_PUBLIC; } if (access_type & ZEND_ACC_STATIC) { - target_symbol_table = ce->static_members; + target_symbol_table = &ce->default_static_properties; } else { target_symbol_table = &ce->default_properties; } @@ -2382,6 +2382,155 @@ return value; } + +static inline zval *new_zval(zend_bool persistent) +{ + zval *z = pemalloc(sizeof(zval), persistent); + INIT_PZVAL(z); + return z; +} + +static inline zval *tmp_zval(void) +{ + zval *z; + ALLOC_ZVAL(z); + z->is_ref = 0; + z->refcount = 0; + return z; +} + +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, &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 = new_zval(ce->type & ZEND_INTERNAL_CLASS); + ZVAL_LONG(constant, value); + 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 = new_zval(ce->type & ZEND_INTERNAL_CLASS); + ZVAL_BOOL(constant, value); + 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 = new_zval(ce->type & ZEND_INTERNAL_CLASS); + ZVAL_DOUBLE(constant, value); + 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 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 = new_zval(ce->type & ZEND_INTERNAL_CLASS); + if (ce->type & ZEND_INTERNAL_CLASS) { + ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0); + } else { + ZVAL_STRINGL(constant, value, value_length, 1); + } + return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC); +} + + +ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, size_t name_len, zval *value TSRMLS_DC) +{ + int retval; + zval **property = NULL; + zend_class_entry *old_scope = EG(scope); + + EG(scope) = scope; + + if (!(property = zend_std_get_static_property(scope, name, name_len, 0 TSRMLS_CC))) { + retval = FAILURE; + } else if (*property == value) { + retval = SUCCESS; + } else { + if (PZVAL_IS_REF(*property)) { + zval_dtor(*property); + (*property)->type = value->type; + (*property)->value = value->value; + + if (value->refcount) { + zval_copy_ctor(*property); + } + + retval = SUCCESS; + } else { + value->refcount++; + if (PZVAL_IS_REF(value)) { + SEPARATE_ZVAL(&value); + } + + retval = zend_hash_update(&scope->static_properties, name, name_len, &value, sizeof(zval *), NULL); + } + } + + if (!value->refcount) { + zval_dtor(value); + FREE_ZVAL(value); + } + + EG(scope) = old_scope; + + return retval; +} + +ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, size_t name_len, zend_bool value TSRMLS_DC) +{ + zval *tmp = tmp_zval(); + ZVAL_BOOL(tmp, value); + return zend_update_static_property(scope, name, name_len, tmp TSRMLS_CC); +} + +ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, size_t name_len, long value TSRMLS_DC) +{ + zval *tmp = tmp_zval(); + ZVAL_LONG(tmp, value); + return zend_update_static_property(scope, name, name_len, tmp TSRMLS_CC); +} + +ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, size_t name_len, double value TSRMLS_DC) +{ + zval *tmp = tmp_zval(); + ZVAL_DOUBLE(tmp, value); + return zend_update_static_property(scope, name, name_len, tmp TSRMLS_CC); +} + +ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, size_t name_len, char *value TSRMLS_DC) +{ + zval *tmp = tmp_zval(); + ZVAL_STRING(tmp, value, 1); + return zend_update_static_property(scope, name, name_len, tmp TSRMLS_CC); +} + +ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, size_t name_len, char *value, size_t value_len TSRMLS_DC) +{ + zval *tmp = tmp_zval(); + ZVAL_STRINGL(tmp, value, value_len, 1); + return zend_update_static_property(scope, name, name_len, tmp TSRMLS_CC); +} + +ZEND_API void zend_init_properties(void *zo TSRMLS_DC) +{ + zend_object *o = (zend_object *) zo; + ALLOC_HASHTABLE(o->properties); + zend_hash_copy(o->properties, &o->ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); +} + +ZEND_API void zend_init_static_properties(zend_class_entry *ce TSRMLS_DC) +{ + zend_hash_copy(&ce->static_properties, &ce->default_static_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); +} /* * Local variables: * tab-width: 4 Index: Zend/zend_API.h =================================================================== RCS file: /repository/ZendEngine2/zend_API.h,v retrieving revision 1.207 diff -u -r1.207 zend_API.h --- Zend/zend_API.h 3 Aug 2005 13:30:47 -0000 1.207 +++ Zend/zend_API.h 9 Aug 2005 21:56:14 -0000 @@ -221,6 +221,24 @@ ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, char *value TSRMLS_DC); ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, char *value, int value_length 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_null(zend_class_entry *ce, char *name, size_t name_length 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_string(zend_class_entry *ce, char *name, size_t name_length, char *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_update_static_property(zend_class_entry *scope, char *name, size_t name_len, zval *value TSRMLS_DC); +ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, size_t name_len, zend_bool value TSRMLS_DC); +ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, size_t name_len, long value TSRMLS_DC); +ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, size_t name_len, double value TSRMLS_DC); +ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, size_t name_len, char *value TSRMLS_DC); +ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, size_t name_len, char *value, size_t value_len TSRMLS_DC); + +ZEND_API void zend_init_properties(void *zo TSRMLS_DC); +ZEND_API void zend_init_static_properties(zend_class_entry *ce 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 zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC); Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.277 diff -u -r1.277 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 3 Aug 2005 13:30:47 -0000 1.277 +++ Zend/zend_builtin_functions.c 9 Aug 2005 21:56:20 -0000 @@ -736,7 +736,7 @@ } else { array_init(return_value); add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC); - add_class_vars(*pce, (*pce)->static_members, return_value TSRMLS_CC); + add_class_vars(*pce, &(*pce)->default_static_properties, return_value TSRMLS_CC); } } /* }}} */ Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647 diff -u -r1.647 zend_compile.c --- Zend/zend_compile.c 4 Aug 2005 14:04:36 -0000 1.647 +++ Zend/zend_compile.c 9 Aug 2005 21:56:30 -0000 @@ -2034,9 +2034,9 @@ zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS); if (child_info->flags & ZEND_ACC_STATIC) { zval **prop; - if (zend_hash_find(parent_ce->static_members, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) { + if (zend_hash_find(&parent_ce->static_properties, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) { zval **new_prop; - if (zend_hash_find(ce->static_members, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) { + if (zend_hash_find(&ce->static_properties, 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; zend_unmangle_property_name(child_info->name, &tmp, &prop_name); @@ -2046,8 +2046,8 @@ } } (*prop)->refcount++; - zend_hash_update(ce->static_members, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL); - zend_hash_del(ce->static_members, prot_name, prot_name_length+1); + zend_hash_update(&ce->static_properties, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL); + zend_hash_del(&ce->static_properties, prot_name, prot_name_length+1); } } else { zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1); @@ -2133,7 +2133,8 @@ /* 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); + zend_hash_merge(&ce->default_static_properties, &parent_ce->default_static_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); + zend_hash_merge(&ce->static_properties, &parent_ce->static_properties, (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); @@ -2263,7 +2264,8 @@ 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_properties); + zend_hash_destroy(&ce->static_properties); zend_hash_destroy(&ce->constants_table); return NULL; } @@ -2718,6 +2720,8 @@ zend_error(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name); } } + + zend_init_static_properties(ce TSRMLS_CC); ce->line_end = zend_get_compiled_lineno(TSRMLS_C); @@ -3927,14 +3931,8 @@ zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0); - - if (persistent_hashes) { - ce->static_members = (HashTable *) malloc(sizeof(HashTable)); - } else { - ALLOC_HASHTABLE(ce->static_members); - } - - zend_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); + zend_hash_init_ex(&ce->default_static_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); + zend_hash_init_ex(&ce->static_properties, 0, NULL, ZVAL_PTR_DTOR, persistent_hashes, 0); zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0); zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0); Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.135 diff -u -r1.135 zend_object_handlers.c --- Zend/zend_object_handlers.c 3 Aug 2005 13:30:55 -0000 1.135 +++ Zend/zend_object_handlers.c 9 Aug 2005 21:56:53 -0000 @@ -820,7 +820,7 @@ return NULL; } - zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval); + zend_hash_quick_find(&tmp_ce->static_properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval); if (!retval) { if (silent) { Index: Zend/zend_opcode.c =================================================================== RCS file: /repository/ZendEngine2/zend_opcode.c,v retrieving revision 1.110 diff -u -r1.110 zend_opcode.c --- Zend/zend_opcode.c 3 Aug 2005 13:30:56 -0000 1.110 +++ Zend/zend_opcode.c 9 Aug 2005 21:56:55 -0000 @@ -142,9 +142,11 @@ /* 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); } + /* static properties *can* contain run-time data - + they ain't constants */ + zend_hash_clean(&(*pce)->static_properties); return 0; } @@ -159,11 +161,11 @@ case ZEND_USER_CLASS: zend_hash_destroy(&ce->default_properties); zend_hash_destroy(&ce->properties_info); - zend_hash_destroy(ce->static_members); - efree(ce->name); + zend_hash_destroy(&ce->default_static_properties); + zend_hash_destroy(&ce->static_properties); zend_hash_destroy(&ce->function_table); - FREE_HASHTABLE(ce->static_members); zend_hash_destroy(&ce->constants_table); + efree(ce->name); if (ce->num_interfaces > 0 && ce->interfaces) { efree(ce->interfaces); } @@ -175,11 +177,11 @@ case ZEND_INTERNAL_CLASS: zend_hash_destroy(&ce->default_properties); zend_hash_destroy(&ce->properties_info); - zend_hash_destroy(ce->static_members); - free(ce->name); + zend_hash_destroy(&ce->default_static_properties); + zend_hash_destroy(&ce->static_properties); zend_hash_destroy(&ce->function_table); - free(ce->static_members); zend_hash_destroy(&ce->constants_table); + free(ce->name); if (ce->num_interfaces > 0) { free(ce->interfaces); } Index: Zend/zend_reflection_api.c =================================================================== RCS file: /repository/ZendEngine2/zend_reflection_api.c,v retrieving revision 1.164 diff -u -r1.164 zend_reflection_api.c --- Zend/zend_reflection_api.c 3 Aug 2005 13:30:56 -0000 1.164 +++ Zend/zend_reflection_api.c 9 Aug 2005 21:57:06 -0000 @@ -2356,7 +2356,7 @@ zend_update_class_constants(ce TSRMLS_CC); array_init(return_value); - zend_hash_copy(Z_ARRVAL_P(return_value), ce->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); + zend_hash_copy(Z_ARRVAL_P(return_value), &ce->static_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } /* }}} */ @@ -3432,7 +3432,7 @@ if ((ref->prop->flags & ZEND_ACC_STATIC)) { zend_update_class_constants(intern->ce TSRMLS_CC); - if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { + if (zend_hash_quick_find(&intern->ce->static_properties, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name); /* Bails out */ } @@ -3478,7 +3478,7 @@ return; } } - prop_table = intern->ce->static_members; + prop_table = &intern->ce->static_properties; } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { return; --------------030005060603000006060302--