Hi Marcus Boerger, you wrote:
> Hello Michael,
>
> a few questions/comments so that i can understand better:
>
> 1) Zend/zend_API.c: <NEW>
> +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);
> +}
> +
>
> If the internal part uses string duplication so shall use the user space
> code.

Yes, the internal part uses zend_strndup() while the userspace part
- I guess - estrndup().


> 2) Zend/zend_API.c: <NEW>
> +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;
> in the caose you utilize this value is a temp thing thus you need to free it
> in all cases but those you directly use it. A failure is definitively a
> thing where you do't use it so it must be fr here.
> +       } else if (*property == value) {
> +               retval = SUCCESS;
> Here you compare the address of a zval, was that intended?
> In case you meant it, then i think it cannot be correct because that should
> never happen, or is that the case you actually want to prevent?
> In case you meant to prohibit from setting the same value again you need
> actual zval comparison which won't work easily for strings.

This is from zend_reflection_api ReflectionProperty::setValue().
I assume it is meant to prevent useless operations,
because when else should the zvals point to the same address?

> +       } else {
> +               if (PZVAL_IS_REF(*property)) {
> +                       zval_dtor(*property);
> +                       (*property)->type = value->type;
> +                       (*property)->value = value->value;
> +
> +                       if (value->refcount) {
> +                               zval_copy_ctor(*property);
> +                       }
> +               } else {
> +                       **property = *value;
> +                       zval_copy_ctor(*property);
> +               }
> +               retval = SUCCESS;
> +       }
> +
> +       if (!value->refcount) {
> +               zval_dtor(value);
> +               FREE_ZVAL(value);
> +       }
> This only works because your zvals are initialized with refcount=0 which
> cannot be right. In the end it should always read here
> zval_ptr_dtor(&value); And tmp_zval() should initialize with refcount=1.

I actually thought that there should be an "else { zval_ptr_dtor(&value) }"?
Every place I looked at where "temporary zvals" are used, initialize them
with refcount=0.

> +
> +       EG(scope) = old_scope;
> +
> +       return retval;
> +}
>
> Your static properties get duplicated and const updated from
>
> 3) Zend/zend.c: static void class_to_unicode(zend_class_entry **ce)
> +       zend_u_hash_init_ex(&new_ce->default_static_properties, 
> (*ce)->default_static_properties.nNumOfElements, NULL, 
> (*ce)->default_static_properties.pDestructor, 1, 1, 0);
> +       zend_hash_copy(&new_ce->default_static_properties, 
> &(*ce)->default_static_properties, (copy_ctor_func_t) zval_ptr_to_unicode, 
> &tmp_zval, sizeof(zval));
> +       zend_u_hash_init_ex(&new_ce->static_properties, 
> (*ce)->static_properties.nNumOfElements, NULL, 
> (*ce)->default_static_properties.pDestructor, 1, 1, 0);
> Why is the above not using
> "(*ce)->default_static_properties.nNumOfElements", since that is the number
> of entries the static property table will have exactly after the copy
> operation on the next line so why not initialize the number to this?

Yeah, this is a matter of optimization which I was not thinking about
in the first place, sorry.

> +       zend_hash_copy(&new_ce->static_properties, &(*ce)->static_properties, 
> (copy_ctor_func_t) zval_ptr_to_unicode, &tmp_zval, sizeof(zval));
>
> 4) Zend/zend_API.c: ZEND_API void 
> zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC)
>                 
> 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);
> Before your patch we have the situation that consts can only be decalred in
> user space. Thus it is ensured that their data is emalloc'd and only ever
> needs to be const-updated once. Now that you have this as well as your
> default static properties it (zend_update_class_constants()) must be called
> once for every request time. Having said that i think we actuall need two
> tables. cor consts as well. I think default_consts and
> default_static_properies never need to be const updated because otherwise
> you wouldn't react on define changes if a defined const is being referred
> to. With this in mind we also face another problem, the problem that
> const-update assumes that the memory was emalloc'd.So what we need to do is
> ensuring that on the first use in a request the two tables default_const and
> default_static_properties get copied to their working tables consts and
> static_properties. After that copy we can update the consts. Now we also
> ensured that for internal classes the values in the defualt_const table and
> default_static_properties table can become malloc'd.

Well, I didn't really get the idea of this const updating yet, so apologize
if I'm totally wrong here.  Ok, so it is a problem that the const updating
routine (whatever it does) assumes that memory was emalloc()'d but why do
constants_table and default_static_properties need to be updated for
every request? They're not supposed to change their values after
declaration, are they?


> 5) Zend/zend_compile.c: ZEND_API void 
> zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers 
> TSRMLS_DC)
> +       zend_u_hash_init_ex(&ce->default_static_properties, 0, NULL, 
> zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
> +       zend_u_hash_init_ex(&ce->static_properties, 0, NULL, ZVAL_PTR_DTOR, 
> persistent_hashes, UG(unicode), 0);
> After reading 4) it should be clear that the values in
> default_static_properties must be malloc'c zval's. With this in mind we of
> course need to specify a corresponding free method insetad of the currently
> used one that assumes the memory was emalloc'd.

Hm...? default_static_properties' destructor is zval_internal_ptr_dtor, so?


> 6) Renamic static_members to static_properties is a very good idea if you
> ask me but it requires that we have this patch ready and set before 5.1 is
> out.

Well, I'm the one who most strongly hopes that, as my HttpResponse class
is just a bad hack until so-called v6.  As you probably know, I'm a first
time extension writer and still learning a lot and my knowledge of the
internals is still quite low.

Thanks,
--
Michael - < mike(@)php.net >

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to