[RFC] Help debugging overloaded objects

From: Date: Mon, 15 Jan 2007 22:31:31 +0000
Subject: [RFC] Help debugging overloaded objects
Groups: php.internals 
Request: Send a blank email to internals+get-27471@lists.php.net to get a copy of this message
Hello internals, the attached patch introduces a new handler to the engine that is supposed to help debugging overloaded objects. It allows to return a temporary hash rather then the object properties. This way an extension can show non properties in var_dump() and print_r(). It will be used in extensions like SimpleXML. To show how it will look like the changes for said extension are alsopresent. Last but not least the handler can be NULL in which case the old behavior is maintained. If noone objects I will commit this by the end of the week. Any comments? Best regards, Marcus

Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.391 diff -u -p -d -r1.391 zend.c --- Zend/zend.c 12 Jan 2007 14:38:07 -0000 1.391 +++ Zend/zend.c 15 Jan 2007 22:23:16 -0000 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.c,v 1.391 2007/01/12 14:38:07 dmitry Exp $ */ +/* $Id: zend.c,v 1.390 2007/01/11 16:47:46 dmitry Exp $ */ #include "zend.h" #include "zend_extensions.h" @@ -581,6 +581,7 @@ ZEND_API void zend_print_zval_r_ex(zend_ HashTable *properties = NULL; zstr class_name = NULL_ZSTR; zend_uint clen; + int is_temp; if (Z_OBJ_HANDLER_P(expr, get_class_name)) { Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC); @@ -593,8 +594,11 @@ ZEND_API void zend_print_zval_r_ex(zend_ if (class_name.v) { efree(class_name.v); } - if (Z_OBJ_HANDLER_P(expr, get_properties)) { + if (Z_OBJ_HANDLER_P(expr, get_debug_info)) { + properties = Z_OBJ_HANDLER_P(expr, get_debug_info)(expr, &is_temp TSRMLS_CC); + } else if (Z_OBJ_HANDLER_P(expr, get_properties)) { properties = Z_OBJPROP_P(expr); + is_temp = 0; } if (properties) { if (++properties->nApplyCount>1) { @@ -604,6 +608,10 @@ ZEND_API void zend_print_zval_r_ex(zend_ } print_hash(properties, indent, 1 TSRMLS_CC); properties->nApplyCount--; + if (is_temp) { + zend_hash_destroy(properties); + efree(properties); + } } break; } Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.182 diff -u -p -d -r1.182 zend_object_handlers.c --- Zend/zend_object_handlers.c 10 Jan 2007 15:59:55 -0000 1.182 +++ Zend/zend_object_handlers.c 15 Jan 2007 22:23:17 -0000 @@ -49,13 +49,19 @@ called, we cal __call handler. */ -static HashTable *zend_std_get_properties(zval *object TSRMLS_DC) +ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) { zend_object *zobj; zobj = Z_OBJ_P(object); return zobj->properties; } +ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC) +{ + *is_temp = 0; + return zend_std_get_properties(object TSRMLS_CC); +} + static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) { zval *retval = NULL; @@ -1186,6 +1192,7 @@ ZEND_API zend_object_handlers std_object zend_std_compare_objects, /* compare_objects */ zend_std_cast_object_tostring, /* cast_object */ NULL, /* count_elements */ + NULL, /* get_debug_info */ }; /* Index: Zend/zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.61 diff -u -p -d -r1.61 zend_object_handlers.h --- Zend/zend_object_handlers.h 1 Jan 2007 09:29:21 -0000 1.61 +++ Zend/zend_object_handlers.h 15 Jan 2007 22:23:17 -0000 @@ -80,6 +80,8 @@ typedef void (*zend_object_unset_dimensi /* Used to get hash of the properties of the object, as hash of zval's */ typedef HashTable *(*zend_object_get_properties_t)(zval *object TSRMLS_DC); +typedef HashTable *(*zend_object_get_debug_info_t)(zval *object, int *is_temp TSRMLS_DC); + /* Used to call methods */ /* args on stack! */ /* Andi - EX(fbc) (function being called) needs to be initialized already in the INIT fcall opcode so that the parameters can be parsed the right way. We need to add another callback for this. @@ -132,6 +134,7 @@ struct _zend_object_handlers { zend_object_compare_t compare_objects; zend_object_cast_t cast_object; zend_object_count_elements_t count_elements; + zend_object_get_debug_info_t get_debug_info; }; extern ZEND_API zend_object_handlers std_object_handlers; @@ -142,7 +145,8 @@ ZEND_API zval **zend_std_get_static_prop ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_uchar type, zstr property_name, int property_name_len TSRMLS_DC); ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC); ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC); - +ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC); +ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC); ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC); Index: ext/simplexml/simplexml.c =================================================================== RCS file: /repository/php-src/ext/simplexml/simplexml.c,v retrieving revision 1.226 diff -u -p -d -r1.226 simplexml.c --- ext/simplexml/simplexml.c 1 Jan 2007 09:29:29 -0000 1.226 +++ ext/simplexml/simplexml.c 15 Jan 2007 22:23:18 -0000 @@ -615,6 +615,7 @@ static void sxe_dimension_write(zval *ob } /* }}} */ +#if HELLY_0 static zval** sxe_property_get_adr(zval *object, zval *member TSRMLS_DC) /* {{{ */ { php_sxe_object *sxe; @@ -639,12 +640,16 @@ static zval** sxe_property_get_adr(zval _node_as_zval(sxe, node, return_value, type, name, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC); sxe = php_sxe_fetch_object(return_value TSRMLS_CC); + if (sxe->tmp) { + zval_ptr_dtor(&sxe->tmp); + } sxe->tmp = return_value; return_value->is_ref = 1; return &sxe->tmp; } /* }}} */ +#endif /* {{{ sxe_prop_dim_exists() */ @@ -946,9 +951,7 @@ static void sxe_properties_add(HashTable } } -/* {{{ sxe_properties_get() - */ -static HashTable * sxe_properties_get(zval *object TSRMLS_DC) +static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{{ */ { zval *value; zval *zattr; @@ -962,7 +965,10 @@ static HashTable * sxe_properties_get(zv sxe = php_sxe_fetch_object(object TSRMLS_CC); - if (sxe->properties) { + if (is_debug) { + ALLOC_HASHTABLE(rv); + zend_u_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode)); + } else if (sxe->properties) { zend_hash_clean(sxe->properties); rv = sxe->properties; } else { @@ -975,7 +981,7 @@ static HashTable * sxe_properties_get(zv if (!node) { return rv; } - if (1||sxe->iter.type != SXE_ITER_CHILD) { + if (is_debug) { if (sxe->iter.type == SXE_ITER_ELEMENT) { node = php_sxe_get_first_node(sxe, node TSRMLS_CC); } @@ -1066,6 +1072,19 @@ next_iter: } /* }}} */ +static HashTable * sxe_get_properties(zval *object TSRMLS_DC) /* {{{ */ +{ + return sxe_get_prop_hash(object, 0 TSRMLS_CC); +} +/* }}} */ + +static HashTable * sxe_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ +{ + *is_temp = 1; + return sxe_get_prop_hash(object, 1 TSRMLS_CC); +} +/* }}} */ + static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{ */ { php_sxe_object *sxe1; @@ -1657,16 +1676,20 @@ static int cast_object(zval *object, int static int sxe_object_cast(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC) { php_sxe_object *sxe; - xmlChar *contents = NULL; + xmlChar *contents = NULL; xmlNodePtr node; - int rv; + int rv; + HashTable *prop_hash; sxe = php_sxe_fetch_object(readobj TSRMLS_CC); if (type == IS_BOOL) { node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC); + prop_hash = sxe_get_prop_hash(readobj, 1 TSRMLS_CC); INIT_PZVAL(writeobj); - ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(sxe_properties_get(readobj TSRMLS_CC)) > 0); + ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(prop_hash) > 0); + zend_hash_destroy(prop_hash); + efree(prop_hash); return SUCCESS; } @@ -1749,14 +1772,14 @@ static zend_object_handlers sxe_object_h sxe_property_write, sxe_dimension_read, sxe_dimension_write, - sxe_property_get_adr, + NULL, sxe_get_value, /* get */ NULL, sxe_property_exists, sxe_property_delete, sxe_dimension_exists, sxe_dimension_delete, - sxe_properties_get, + sxe_get_properties, NULL, /* zend_get_std_object_handlers()->get_method,*/ NULL, /* zend_get_std_object_handlers()->call_method,*/ NULL, /* zend_get_std_object_handlers()->get_constructor, */ @@ -1764,7 +1787,8 @@ static zend_object_handlers sxe_object_h NULL, /* zend_get_std_object_handlers()->get_class_name,*/ sxe_objects_compare, sxe_object_cast, - sxe_count_elements + sxe_count_elements, + sxe_get_debug_info }; /* {{{ sxe_object_clone() Index: ext/standard/var.c =================================================================== RCS file: /repository/php-src/ext/standard/var.c,v retrieving revision 1.259 diff -u -p -d -r1.259 var.c --- ext/standard/var.c 1 Jan 2007 09:29:32 -0000 1.259 +++ ext/standard/var.c 15 Jan 2007 22:23:18 -0000 @@ -181,6 +181,7 @@ PHPAPI void php_var_dump(zval **struc, i zstr class_name; zend_uint class_name_len; int (*php_element_dump_func)(zval**, int, va_list, zend_hash_key*); + int is_temp; if (level > 1) { php_printf("%*c", level - 1, ' '); @@ -217,9 +218,10 @@ PHPAPI void php_var_dump(zval **struc, i } php_printf("%sarray(%d) {\n", COMMON, zend_hash_num_elements(myht)); php_element_dump_func = php_array_element_dump; + is_temp = 0; goto head_done; case IS_OBJECT: - myht = Z_OBJPROP_PP(struc); + myht = Z_OBJ_HANDLER_PP(struc, get_debug_info)(*struc, &is_temp TSRMLS_CC); if (myht && myht->nApplyCount > 1) { PUTS("*RECURSION*\n"); return; @@ -237,6 +239,10 @@ head_done: php_printf("%*c", level-1, ' '); } PUTS("}\n"); + if (is_temp) { + zend_hash_destroy(myht); + efree(myht); + } break; case IS_RESOURCE: { char *type_name;
« previous php.internals (#27471) next »