]> granicus.if.org Git - php/commitdiff
Use object apply count in var_dump / print_r
authorNikita Popov <nikic@php.net>
Wed, 15 Apr 2015 19:07:34 +0000 (21:07 +0200)
committerNikita Popov <nikic@php.net>
Wed, 15 Apr 2015 20:00:12 +0000 (22:00 +0200)
Instead of using the array apply count on the debug_info array, use
the object apply count for recursion detection when dumping. This
handles recursion in a more generic way and does not require each
debug_info handler to deal with this.

This allows returning a temporary debug_info array, instead of
having to store it in the object (thus delaying destruction of the
values).

Switch SPL debug_info handlers to use a temporary array.

Zend/zend.c
ext/spl/spl_array.c
ext/spl/spl_dllist.c
ext/spl/spl_heap.c
ext/spl/spl_observer.c
ext/standard/var.c

index 77e0b624c01c459cbffc737adbf52b90c3baab96..03082de4d6e214a1d313943727f2bfead1d41bda 100644 (file)
@@ -296,17 +296,18 @@ ZEND_API void zend_print_flat_zval_r(zval *expr) /* {{{ */
                        zend_printf("%s Object (", class_name->val);
                        zend_string_release(class_name);
 
+                       if (Z_OBJ_APPLY_COUNT_P(expr) > 0) {
+                               ZEND_PUTS(" *RECURSION*");
+                               return;
+                       }
+
                        if (Z_OBJ_HANDLER_P(expr, get_properties)) {
                                properties = Z_OBJPROP_P(expr);
                        }
                        if (properties) {
-                               if (++properties->u.v.nApplyCount>1) {
-                                       ZEND_PUTS(" *RECURSION*");
-                                       properties->u.v.nApplyCount--;
-                                       return;
-                               }
+                               Z_OBJ_INC_APPLY_COUNT_P(expr);
                                print_flat_hash(properties);
-                               properties->u.v.nApplyCount--;
+                               Z_OBJ_DEC_APPLY_COUNT_P(expr);
                        }
                        ZEND_PUTS(")");
                        break;
@@ -351,16 +352,18 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
                                zend_string_release(class_name);
 
                                ZEND_PUTS_EX(" Object\n");
-                               if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
-                                       break;
-                               }
-                               if (++properties->u.v.nApplyCount>1) {
+                               if (Z_OBJ_APPLY_COUNT_P(expr) > 0) {
                                        ZEND_PUTS_EX(" *RECURSION*");
-                                       properties->u.v.nApplyCount--;
                                        return;
                                }
+                               if ((properties = Z_OBJDEBUG_P(expr, is_temp)) == NULL) {
+                                       break;
+                               }
+
+                               Z_OBJ_INC_APPLY_COUNT_P(expr);
                                print_hash(write_func, properties, indent, 1);
-                               properties->u.v.nApplyCount--;
+                               Z_OBJ_DEC_APPLY_COUNT_P(expr);
+
                                if (is_temp) {
                                        zend_hash_destroy(properties);
                                        FREE_HASHTABLE(properties);
index 76392381ef4bb1e0a0710740e46bf8fcb10b5f94..78fe94c6085110d99e638cb032ce9e8ad7f5eeb7 100644 (file)
@@ -73,7 +73,6 @@ typedef struct _spl_array_object {
        zend_function     *fptr_offset_del;
        zend_function     *fptr_count;
        zend_class_entry* ce_get_iterator;
-       HashTable         *debug_info;
        unsigned char     nApplyCount;
        zend_object       std;
 } spl_array_object;
@@ -131,11 +130,6 @@ static void spl_array_object_free_storage(zend_object *object)
        zend_object_std_dtor(&intern->std);
 
        zval_ptr_dtor(&intern->array);
-
-       if (intern->debug_info != NULL) {
-               zend_hash_destroy(intern->debug_info);
-               efree(intern->debug_info);
-       }
 }
 /* }}} */
 
@@ -154,7 +148,6 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval *
        object_properties_init(&intern->std, class_type);
 
        intern->ar_flags = 0;
-       intern->debug_info       = NULL;
        intern->ce_get_iterator = spl_ce_ArrayIterator;
        if (orig) {
                spl_array_object *other = Z_SPLARRAY_P(orig);
@@ -806,34 +799,31 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */
        zend_class_entry *base;
        spl_array_object *intern = Z_SPLARRAY_P(obj);
 
-       *is_temp = 0;
-
        if (!intern->std.properties) {
                rebuild_object_properties(&intern->std);
        }
 
        if (HASH_OF(&intern->array) == intern->std.properties) {
+               *is_temp = 0;
                return intern->std.properties;
        } else {
-               if (intern->debug_info == NULL) {
-                       ALLOC_HASHTABLE(intern->debug_info);
-                       ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
-               }
+               HashTable *debug_info;
+               *is_temp = 1;
 
-               if (intern->debug_info->u.v.nApplyCount == 0) {
-                       zend_hash_clean(intern->debug_info);
-                       zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
+               ALLOC_HASHTABLE(debug_info);
+               ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+               zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
 
-                       storage = &intern->array;
-                       Z_TRY_ADDREF_P(storage);
+               storage = &intern->array;
+               Z_TRY_ADDREF_P(storage);
 
-                       base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject;
-                       zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1);
-                       zend_symtable_update(intern->debug_info, zname, storage);
-                       zend_string_release(zname);
-               }
+               base = Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator
+                       ? spl_ce_ArrayIterator : spl_ce_ArrayObject;
+               zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1);
+               zend_symtable_update(debug_info, zname, storage);
+               zend_string_release(zname);
 
-               return intern->debug_info;
+               return debug_info;
        }
 }
 /* }}} */
index 68c46486e10ac17085a5ecb85100cc94a2fe1e36..6406670e2e0ffd6598fd3f17783242c02b4479fe 100644 (file)
@@ -93,7 +93,6 @@ struct _spl_dllist_object {
        zend_function         *fptr_offset_del;
        zend_function         *fptr_count;
        zend_class_entry      *ce_get_iterator;
-       HashTable             *debug_info;
        zend_object            std;
 };
 
@@ -357,11 +356,6 @@ static void spl_dllist_object_free_storage(zend_object *object) /* {{{ */
 
        spl_ptr_llist_destroy(intern->llist);
        SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
-
-       if (intern->debug_info != NULL) {
-               zend_hash_destroy(intern->debug_info);
-               efree(intern->debug_info);
-       }
 }
 /* }}} */
 
@@ -380,7 +374,6 @@ static zend_object *spl_dllist_object_new_ex(zend_class_entry *class_type, zval
 
        intern->flags = 0;
        intern->traverse_position = 0;
-       intern->debug_info = NULL;
 
        if (orig) {
                spl_dllist_object *other = Z_SPLDLLIST_P(orig);
@@ -500,46 +493,41 @@ static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp) /* {
        zval tmp, dllist_array;
        zend_string *pnstr;
        int  i = 0;
+       HashTable *debug_info;
+       *is_temp = 1;
 
-       *is_temp = 0;
-
-       if (intern->debug_info == NULL) {
-               ALLOC_HASHTABLE(intern->debug_info);
-               zend_hash_init(intern->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
        }
 
-       if (intern->debug_info->u.v.nApplyCount == 0) {
-
-               if (!intern->std.properties) {
-                       rebuild_object_properties(&intern->std);
-               }
-               zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
-
-               pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1);
-               ZVAL_LONG(&tmp, intern->flags);
-               zend_hash_add(intern->debug_info, pnstr, &tmp);
-               zend_string_release(pnstr);
+       ALLOC_HASHTABLE(debug_info);
+       zend_hash_init(debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
 
-               array_init(&dllist_array);
+       pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1);
+       ZVAL_LONG(&tmp, intern->flags);
+       zend_hash_add(debug_info, pnstr, &tmp);
+       zend_string_release(pnstr);
 
-               while (current) {
-                       next = current->next;
+       array_init(&dllist_array);
 
-                       add_index_zval(&dllist_array, i, &current->data);
-                       if (Z_REFCOUNTED(current->data)) {
-                               Z_ADDREF(current->data);
-                       }
-                       i++;
+       while (current) {
+               next = current->next;
 
-                       current = next;
+               add_index_zval(&dllist_array, i, &current->data);
+               if (Z_REFCOUNTED(current->data)) {
+                       Z_ADDREF(current->data);
                }
+               i++;
 
-               pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1);
-               zend_hash_add(intern->debug_info, pnstr, &dllist_array);
-               zend_string_release(pnstr);
+               current = next;
        }
 
-       return intern->debug_info;
+       pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1);
+       zend_hash_add(debug_info, pnstr, &dllist_array);
+       zend_string_release(pnstr);
+
+       return debug_info;
 }
 /* }}}} */
 
index 98f4217be9c7a1e2a50a879778259c03542a21f2..825344ff2187a2c310afd421f3355fbd8e206a2d 100644 (file)
@@ -73,7 +73,6 @@ struct _spl_heap_object {
        zend_class_entry   *ce_get_iterator;
        zend_function      *fptr_cmp;
        zend_function      *fptr_count;
-       HashTable          *debug_info;
        zend_object         std;
 };
 
@@ -369,11 +368,6 @@ static void spl_heap_object_free_storage(zend_object *object) /* {{{ */
        }
 
        spl_ptr_heap_destroy(intern->heap);
-
-       if (intern->debug_info != NULL) {
-               zend_hash_destroy(intern->debug_info);
-               efree(intern->debug_info);
-       }
 }
 /* }}} */
 
@@ -390,7 +384,6 @@ static zend_object *spl_heap_object_new_ex(zend_class_entry *class_type, zval *o
 
        intern->flags      = 0;
        intern->fptr_cmp   = NULL;
-       intern->debug_info = NULL;
 
        if (orig) {
                spl_heap_object *other = Z_SPLHEAP_P(orig);
@@ -506,48 +499,43 @@ static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zv
        spl_heap_object *intern  = Z_SPLHEAP_P(obj);
        zval tmp, heap_array;
        zend_string *pnstr;
+       HashTable *debug_info;
        int  i;
 
-       *is_temp = 0;
+       *is_temp = 1;
 
        if (!intern->std.properties) {
                rebuild_object_properties(&intern->std);
        }
 
-       if (intern->debug_info == NULL) {
-               ALLOC_HASHTABLE(intern->debug_info);
-               ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
-       }
-
-       if (intern->debug_info->u.v.nApplyCount == 0) {
-
-               zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
+       ALLOC_HASHTABLE(debug_info);
+       ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+       zend_hash_copy(debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref);
 
-               pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1);
-               ZVAL_LONG(&tmp, intern->flags);
-               zend_hash_update(intern->debug_info, pnstr, &tmp);
-               zend_string_release(pnstr);
+       pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1);
+       ZVAL_LONG(&tmp, intern->flags);
+       zend_hash_update(debug_info, pnstr, &tmp);
+       zend_string_release(pnstr);
 
-               pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1);
-               ZVAL_BOOL(&tmp, intern->heap->flags&SPL_HEAP_CORRUPTED);
-               zend_hash_update(intern->debug_info, pnstr, &tmp);
-               zend_string_release(pnstr);
+       pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1);
+       ZVAL_BOOL(&tmp, intern->heap->flags&SPL_HEAP_CORRUPTED);
+       zend_hash_update(debug_info, pnstr, &tmp);
+       zend_string_release(pnstr);
 
-               array_init(&heap_array);
+       array_init(&heap_array);
 
-               for (i = 0; i < intern->heap->count; ++i) {
-                       add_index_zval(&heap_array, i, &intern->heap->elements[i]);
-                       if (Z_REFCOUNTED(intern->heap->elements[i])) {
-                               Z_ADDREF(intern->heap->elements[i]);
-                       }
+       for (i = 0; i < intern->heap->count; ++i) {
+               add_index_zval(&heap_array, i, &intern->heap->elements[i]);
+               if (Z_REFCOUNTED(intern->heap->elements[i])) {
+                       Z_ADDREF(intern->heap->elements[i]);
                }
-
-               pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1);
-               zend_hash_update(intern->debug_info, pnstr, &heap_array);
-               zend_string_release(pnstr);
        }
 
-       return intern->debug_info;
+       pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1);
+       zend_hash_update(debug_info, pnstr, &heap_array);
+       zend_string_release(pnstr);
+
+       return debug_info;
 }
 /* }}} */
 
index 76933a8228920b67a1ad1d64c4c20acbcf1e509e..b508565c83ffdedd556bdfe49fdadd95db7632b5 100644 (file)
@@ -85,7 +85,6 @@ typedef struct _spl_SplObjectStorage { /* {{{ */
        HashPosition      pos;
        zend_long         flags;
        zend_function    *fptr_get_hash;
-       HashTable        *debug_info;
        zval             *gcdata;
        size_t            gcdata_num;
        zend_object       std;
@@ -112,11 +111,6 @@ void spl_SplObjectStorage_free_storage(zend_object *object) /* {{{ */
 
        zend_hash_destroy(&intern->storage);
 
-       if (intern->debug_info != NULL) {
-               zend_hash_destroy(intern->debug_info);
-               efree(intern->debug_info);
-       }
-
        if (intern->gcdata != NULL) {
                efree(intern->gcdata);
        }
@@ -320,39 +314,35 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp) /* {{{
        zval tmp, storage;
        zend_string *md5str;
        zend_string *zname;
+       HashTable *debug_info;
 
-       *is_temp = 0;
+       *is_temp = 1;
 
        props = Z_OBJPROP_P(obj);
 
-       if (intern->debug_info == NULL) {
-               ALLOC_HASHTABLE(intern->debug_info);
-               ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(props) + 1, 0);
-       }
-
-       if (intern->debug_info->u.v.nApplyCount == 0) {
-               zend_hash_copy(intern->debug_info, props, (copy_ctor_func_t)zval_add_ref);
+       ALLOC_HASHTABLE(debug_info);
+       ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(props) + 1, 0);
+       zend_hash_copy(debug_info, props, (copy_ctor_func_t)zval_add_ref);
 
-               array_init(&storage);
+       array_init(&storage);
 
-               ZEND_HASH_FOREACH_PTR(&intern->storage, element) {
-                       md5str = php_spl_object_hash(&element->obj);
-                       array_init(&tmp);
-                       /* Incrementing the refcount of obj and inf would confuse the garbage collector.
-                        * Prefer to null the destructor */
-                       Z_ARRVAL_P(&tmp)->pDestructor = NULL;
-                       add_assoc_zval_ex(&tmp, "obj", sizeof("obj") - 1, &element->obj);
-                       add_assoc_zval_ex(&tmp, "inf", sizeof("inf") - 1, &element->inf);
-                       zend_hash_update(Z_ARRVAL(storage), md5str, &tmp);
-                       zend_string_release(md5str);
-               } ZEND_HASH_FOREACH_END();
+       ZEND_HASH_FOREACH_PTR(&intern->storage, element) {
+               md5str = php_spl_object_hash(&element->obj);
+               array_init(&tmp);
+               /* Incrementing the refcount of obj and inf would confuse the garbage collector.
+                * Prefer to null the destructor */
+               Z_ARRVAL_P(&tmp)->pDestructor = NULL;
+               add_assoc_zval_ex(&tmp, "obj", sizeof("obj") - 1, &element->obj);
+               add_assoc_zval_ex(&tmp, "inf", sizeof("inf") - 1, &element->inf);
+               zend_hash_update(Z_ARRVAL(storage), md5str, &tmp);
+               zend_string_release(md5str);
+       } ZEND_HASH_FOREACH_END();
 
-               zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1);
-               zend_symtable_update(intern->debug_info, zname, &storage);
-               zend_string_release(zname);
-       }
+       zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1);
+       zend_symtable_update(debug_info, zname, &storage);
+       zend_string_release(zname);
 
-       return intern->debug_info;
+       return debug_info;
 }
 /* }}} */
 
index 64926d174b1a13606f6369bbfc250cc45c672b97..fc6be9234a359d3d1119712ed0d984155fecf202 100644 (file)
@@ -62,7 +62,7 @@ static void php_array_element_dump(zval *zv, zend_ulong index, zend_string *key,
                php_printf("%*c[\"", level + 1, ' ');
                PHPWRITE(key->val, key->len);
                php_printf("\"]=>\n");
-               }
+       }
        php_var_dump(zv, level + 2);
 }
 /* }}} */
@@ -156,13 +156,13 @@ again:
                        PUTS("}\n");
                        break;
                case IS_OBJECT:
-                       myht = Z_OBJDEBUG_P(struc, is_temp);
-                       if (myht && ++myht->u.v.nApplyCount > 1) {
+                       if (Z_OBJ_APPLY_COUNT_P(struc) > 0) {
                                PUTS("*RECURSION*\n");
-                               --myht->u.v.nApplyCount;
                                return;
                        }
+                       Z_OBJ_INC_APPLY_COUNT_P(struc);
 
+                       myht = Z_OBJDEBUG_P(struc, is_temp);
                        class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
                        php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0);
                        zend_string_release(class_name);
@@ -175,7 +175,6 @@ again:
                                ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
                                        php_object_property_dump(val, num, key, level);
                                } ZEND_HASH_FOREACH_END();
-                               --myht->u.v.nApplyCount;
                                if (is_temp) {
                                        zend_hash_destroy(myht);
                                        efree(myht);
@@ -185,6 +184,7 @@ again:
                                php_printf("%*c", level-1, ' ');
                        }
                        PUTS("}\n");
+                       Z_OBJ_DEC_APPLY_COUNT_P(struc);
                        break;
                case IS_RESOURCE: {
                        const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));