PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_5_3/Zend - zend_objects_API.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 169
Code covered: 75.7 % Executed lines: 128
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 2.00 of the Zend license,     |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.zend.com/license/2_00.txt.                                |
      11                 :    | If you did not receive a copy of the Zend license and are unable to  |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@zend.com so we can mail you a copy immediately.              |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16                 :    |          Zeev Suraski <zeev@zend.com>                                |
      17                 :    +----------------------------------------------------------------------+
      18                 : */
      19                 : 
      20                 : /* $Id: zend_objects_API.c 275561 2009-02-11 09:58:23Z tony2001 $ */
      21                 : 
      22                 : #include "zend.h"
      23                 : #include "zend_globals.h"
      24                 : #include "zend_variables.h"
      25                 : #include "zend_API.h"
      26                 : #include "zend_objects_API.h"
      27                 : 
      28                 : #define ZEND_DEBUG_OBJECTS 0
      29                 : 
      30                 : ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size)
      31           17619 : {
      32           17619 :         objects->object_buckets = (zend_object_store_bucket *) emalloc(init_size * sizeof(zend_object_store_bucket));
      33           17619 :         objects->top = 1; /* Skip 0 so that handles are true */
      34           17619 :         objects->size = init_size;
      35           17619 :         objects->free_list_head = -1;
      36           17619 :         memset(&objects->object_buckets[0], 0, sizeof(zend_object_store_bucket));
      37           17619 : }
      38                 : 
      39                 : ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
      40           17651 : {
      41           17651 :         efree(objects->object_buckets);
      42           17651 :         objects->object_buckets = NULL;
      43           17651 : }
      44                 : 
      45                 : ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC)
      46           17651 : {
      47           17651 :         zend_uint i = 1;
      48                 : 
      49           51896 :         for (i = 1; i < objects->top ; i++) {
      50           34245 :                 if (objects->object_buckets[i].valid) {
      51           19211 :                         struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
      52                 : 
      53           19211 :                         if (!objects->object_buckets[i].destructor_called) {
      54           18930 :                                 objects->object_buckets[i].destructor_called = 1;
      55           18930 :                                 if (obj->dtor && obj->object) {
      56           18930 :                                         obj->refcount++;
      57           18930 :                                         obj->dtor(obj->object, i TSRMLS_CC);
      58           18930 :                                         obj = &objects->object_buckets[i].bucket.obj;
      59           18930 :                                         obj->refcount--;
      60                 :                                 }
      61                 :                         }
      62                 :                 }
      63                 :         }
      64           17651 : }
      65                 : 
      66                 : ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC)
      67             528 : {
      68                 :         zend_uint i;
      69                 : 
      70             528 :         if (!objects->object_buckets) {
      71               2 :                 return;
      72                 :         }
      73             965 :         for (i = 1; i < objects->top ; i++) {
      74             439 :                 if (objects->object_buckets[i].valid) {
      75             383 :                         objects->object_buckets[i].destructor_called = 1;
      76                 :                 }
      77                 :         }
      78                 : }
      79                 : 
      80                 : ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC)
      81           17651 : {
      82           17651 :         zend_uint i = 1;
      83                 : 
      84           51896 :         for (i = 1; i < objects->top ; i++) {
      85           34245 :                 if (objects->object_buckets[i].valid) {
      86             535 :                         struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
      87                 : 
      88             535 :                         GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
      89                 : 
      90             535 :                         objects->object_buckets[i].valid = 0;
      91             535 :                         if (obj->free_storage) {
      92             534 :                                 obj->free_storage(obj->object TSRMLS_CC);
      93                 :                         }
      94                 :                         /* Not adding to free list as we are shutting down anyway */
      95                 :                 }
      96                 :         }
      97           17651 : }
      98                 : 
      99                 : 
     100                 : /* Store objects API */
     101                 : 
     102                 : ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_free_object_storage_t free_storage, zend_objects_store_clone_t clone TSRMLS_DC)
     103          892134 : {
     104                 :         zend_object_handle handle;
     105                 :         struct _store_object *obj;
     106                 : 
     107          892134 :         if (EG(objects_store).free_list_head != -1) {
     108          857889 :                 handle = EG(objects_store).free_list_head;
     109          857889 :                 EG(objects_store).free_list_head = EG(objects_store).object_buckets[handle].bucket.free_list.next;
     110                 :         } else {
     111           34245 :                 if (EG(objects_store).top == EG(objects_store).size) {
     112               6 :                         EG(objects_store).size <<= 1;
     113               6 :                         EG(objects_store).object_buckets = (zend_object_store_bucket *) erealloc(EG(objects_store).object_buckets, EG(objects_store).size * sizeof(zend_object_store_bucket));
     114                 :                 }
     115           34245 :                 handle = EG(objects_store).top++;
     116                 :         }
     117          892134 :         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     118          892134 :         EG(objects_store).object_buckets[handle].destructor_called = 0;
     119          892134 :         EG(objects_store).object_buckets[handle].valid = 1;
     120                 : 
     121          892134 :         obj->refcount = 1;
     122          892134 :         GC_OBJ_INIT(obj);
     123          892134 :         obj->object = object;
     124          892134 :         obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
     125          892134 :         obj->free_storage = free_storage;
     126          892134 :         obj->clone = clone;
     127          892134 :         obj->handlers = NULL;
     128                 : 
     129                 : #if ZEND_DEBUG_OBJECTS
     130                 :         fprintf(stderr, "Allocated object id #%d\n", handle);
     131                 : #endif
     132          892134 :         return handle;
     133                 : }
     134                 : 
     135                 : ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC)
     136              18 : {
     137              18 :         zend_object_handle handle = Z_OBJ_HANDLE_P(object);
     138                 : 
     139              18 :         return EG(objects_store).object_buckets[handle].bucket.obj.refcount;
     140                 : }
     141                 : 
     142                 : ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC)
     143          218433 : {
     144          218433 :         zend_object_handle handle = Z_OBJ_HANDLE_P(object);
     145                 : 
     146          218433 :         EG(objects_store).object_buckets[handle].bucket.obj.refcount++;
     147                 : #if ZEND_DEBUG_OBJECTS
     148                 :         fprintf(stderr, "Increased refcount of object id #%d\n", handle);
     149                 : #endif
     150          218433 : }
     151                 : 
     152                 : /*
     153                 :  * Add a reference to an objects store entry given the object handle.
     154                 :  */
     155                 : ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC)
     156               0 : {
     157               0 :         EG(objects_store).object_buckets[handle].bucket.obj.refcount++;
     158               0 : }
     159                 : 
     160                 : #define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST()                                                                                                                                   \
     161                 :                         EG(objects_store).object_buckets[handle].bucket.free_list.next = EG(objects_store).free_list_head;      \
     162                 :                         EG(objects_store).free_list_head = handle;                                                                                                                      \
     163                 :                         EG(objects_store).object_buckets[handle].valid = 0;
     164                 : 
     165                 : ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC)
     166         1100163 : {
     167                 :         zend_object_handle handle;
     168                 : 
     169         1100163 :         handle = Z_OBJ_HANDLE_P(zobject);
     170                 : 
     171         1100163 :         Z_ADDREF_P(zobject);
     172         1100163 :         zend_objects_store_del_ref_by_handle_ex(handle, Z_OBJ_HT_P(zobject) TSRMLS_CC);
     173         1100158 :         Z_DELREF_P(zobject);
     174                 : 
     175         1100158 :         GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject);
     176         1100158 : }
     177                 : 
     178                 : /*
     179                 :  * Delete a reference to an objects store entry given the object handle.
     180                 :  */
     181                 : ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC) /* {{{ */
     182         1100184 : {
     183                 :         struct _store_object *obj;
     184         1100184 :         int failure = 0;
     185                 : 
     186         1100184 :         if (!EG(objects_store).object_buckets) {
     187               2 :                 return;
     188                 :         }
     189                 : 
     190         1100182 :         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     191                 : 
     192                 :         /*      Make sure we hold a reference count during the destructor call
     193                 :                 otherwise, when the destructor ends the storage might be freed
     194                 :                 when the refcount reaches 0 a second time
     195                 :          */
     196         1100182 :         if (EG(objects_store).object_buckets[handle].valid) {
     197         1100026 :                 if (obj->refcount == 1) {
     198          891601 :                         if (!EG(objects_store).object_buckets[handle].destructor_called) {
     199          872512 :                                 EG(objects_store).object_buckets[handle].destructor_called = 1;
     200                 : 
     201          872512 :                                 if (obj->dtor) {
     202          872512 :                                         if (handlers && !obj->handlers) {
     203          872506 :                                                 obj->handlers = handlers;
     204                 :                                         }
     205          872512 :                                         zend_try {
     206          872512 :                                                 obj->dtor(obj->object, handle TSRMLS_CC);
     207               4 :                                         } zend_catch {
     208               4 :                                                 failure = 1;
     209          872512 :                                         } zend_end_try();
     210                 :                                 }
     211                 :                         }
     212                 :                         
     213                 :                         /* re-read the object from the object store as the store might have been reallocated in the dtor */
     214          891601 :                         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     215                 : 
     216          891601 :                         if (obj->refcount == 1) {
     217          891598 :                                 GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
     218          891598 :                                 if (obj->free_storage) {
     219          890989 :                                         zend_try {
     220          890989 :                                                 obj->free_storage(obj->object TSRMLS_CC);
     221               1 :                                         } zend_catch {
     222               1 :                                                 failure = 1;
     223          890989 :                                         } zend_end_try();
     224                 :                                 }
     225          891598 :                                 ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST();
     226                 :                         }
     227                 :                 }
     228                 :         }
     229                 : 
     230         1100182 :         obj->refcount--;
     231                 : 
     232                 : #if ZEND_DEBUG_OBJECTS
     233                 :         if (obj->refcount == 0) {
     234                 :                 fprintf(stderr, "Deallocated object id #%d\n", handle);
     235                 :         } else {
     236                 :                 fprintf(stderr, "Decreased refcount of object id #%d\n", handle);
     237                 :         }
     238                 : #endif
     239         1100182 :         if (failure) {
     240               5 :                 zend_bailout();
     241                 :         }
     242                 : }
     243                 : /* }}} */
     244                 : 
     245                 : ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
     246               6 : {
     247                 :         zend_object_value retval;
     248                 :         void *new_object;
     249                 :         struct _store_object *obj;
     250               6 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     251                 : 
     252               6 :         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     253                 : 
     254               6 :         if (obj->clone == NULL) {
     255               0 :                 zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name);
     256                 :         }
     257                 : 
     258               6 :         obj->clone(obj->object, &new_object TSRMLS_CC);
     259               6 :         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     260                 : 
     261               6 :         retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->free_storage, obj->clone TSRMLS_CC);
     262               6 :         retval.handlers = Z_OBJ_HT_P(zobject);
     263               6 :         EG(objects_store).object_buckets[handle].bucket.obj.handlers = retval.handlers;
     264                 : 
     265               6 :         return retval;
     266                 : }
     267                 : 
     268                 : ZEND_API void *zend_object_store_get_object(const zval *zobject TSRMLS_DC)
     269         2470182 : {
     270         2470182 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     271                 : 
     272         2470182 :         return EG(objects_store).object_buckets[handle].bucket.obj.object;
     273                 : }
     274                 : 
     275                 : /*
     276                 :  * Retrieve an entry from the objects store given the object handle.
     277                 :  */
     278                 : ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle TSRMLS_DC)
     279               0 : {
     280               0 :         return EG(objects_store).object_buckets[handle].bucket.obj.object;
     281                 : }
     282                 : 
     283                 : /* zend_object_store_set_object:
     284                 :  * It is ONLY valid to call this function from within the constructor of an
     285                 :  * overloaded object.  Its purpose is to set the object pointer for the object
     286                 :  * when you can't possibly know its value until you have parsed the arguments
     287                 :  * from the constructor function.  You MUST NOT use this function for any other
     288                 :  * weird games, or call it at any other time after the object is constructed.
     289                 :  * */
     290                 : ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC)
     291              31 : {
     292              31 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     293                 : 
     294              31 :         EG(objects_store).object_buckets[handle].bucket.obj.object = object;
     295              31 : }
     296                 : 
     297                 : 
     298                 : /* Called when the ctor was terminated by an exception */
     299                 : ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC)
     300             292 : {
     301             292 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     302             292 :         zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle];
     303                 :         
     304             292 :         obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);;
     305             292 :         obj_bucket->destructor_called = 1;
     306             292 : }
     307                 : 
     308                 : 
     309                 : /* Proxy objects workings */
     310                 : typedef struct _zend_proxy_object {
     311                 :         zval *object;
     312                 :         zval *property;
     313                 : } zend_proxy_object;
     314                 : 
     315                 : static zend_object_handlers zend_object_proxy_handlers;
     316                 : 
     317                 : ZEND_API void zend_objects_proxy_free_storage(zend_proxy_object *object TSRMLS_DC)
     318               0 : {
     319               0 :         zval_ptr_dtor(&object->object);
     320               0 :         zval_ptr_dtor(&object->property);
     321               0 :         efree(object);
     322               0 : }
     323                 : 
     324                 : ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC)
     325               0 : {
     326               0 :         *object_clone = emalloc(sizeof(zend_proxy_object));
     327               0 :         (*object_clone)->object = object->object;
     328               0 :         (*object_clone)->property = object->property;
     329               0 :         zval_add_ref(&(*object_clone)->property);
     330               0 :         zval_add_ref(&(*object_clone)->object);
     331               0 : }
     332                 : 
     333                 : ZEND_API zval *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC)
     334               0 : {
     335               0 :         zend_proxy_object *pobj = emalloc(sizeof(zend_proxy_object));
     336                 :         zval *retval;
     337                 : 
     338               0 :         pobj->object = object;
     339               0 :         pobj->property = member;
     340               0 :         zval_add_ref(&pobj->property);
     341               0 :         zval_add_ref(&pobj->object);
     342                 : 
     343               0 :         MAKE_STD_ZVAL(retval);
     344               0 :         Z_TYPE_P(retval) = IS_OBJECT;
     345               0 :         Z_OBJ_HANDLE_P(retval) = zend_objects_store_put(pobj, NULL, (zend_objects_free_object_storage_t) zend_objects_proxy_free_storage, (zend_objects_store_clone_t) zend_objects_proxy_clone TSRMLS_CC);
     346               0 :         Z_OBJ_HT_P(retval) = &zend_object_proxy_handlers;
     347                 : 
     348               0 :         return retval;
     349                 : }
     350                 : 
     351                 : ZEND_API void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC)
     352               0 : {
     353               0 :         zend_proxy_object *probj = zend_object_store_get_object(*property TSRMLS_CC);
     354                 : 
     355               0 :         if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->write_property) {
     356               0 :                 Z_OBJ_HT_P(probj->object)->write_property(probj->object, probj->property, value TSRMLS_CC);
     357                 :         } else {
     358               0 :                 zend_error(E_WARNING, "Cannot write property of object - no write handler defined");
     359                 :         }
     360               0 : }
     361                 : 
     362                 : ZEND_API zval* zend_object_proxy_get(zval *property TSRMLS_DC)
     363               0 : {
     364               0 :         zend_proxy_object *probj = zend_object_store_get_object(property TSRMLS_CC);
     365                 : 
     366               0 :         if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->read_property) {
     367               0 :                 return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property, BP_VAR_R TSRMLS_CC);
     368                 :         } else {
     369               0 :                 zend_error(E_WARNING, "Cannot read property of object - no read handler defined");
     370                 :         }
     371                 : 
     372               0 :         return NULL;
     373                 : }
     374                 : 
     375                 : ZEND_API zend_object_handlers *zend_get_std_object_handlers(void)
     376          670751 : {
     377          670751 :         return &std_object_handlers;
     378                 : }
     379                 : 
     380                 : static zend_object_handlers zend_object_proxy_handlers = {
     381                 :         ZEND_OBJECTS_STORE_HANDLERS,
     382                 : 
     383                 :         NULL,                                           /* read_property */
     384                 :         NULL,                                           /* write_property */
     385                 :         NULL,                                           /* read dimension */
     386                 :         NULL,                                           /* write_dimension */
     387                 :         NULL,                                           /* get_property_ptr_ptr */
     388                 :         zend_object_proxy_get,          /* get */
     389                 :         zend_object_proxy_set,          /* set */
     390                 :         NULL,                                           /* has_property */
     391                 :         NULL,                                           /* unset_property */
     392                 :         NULL,                                           /* has_dimension */
     393                 :         NULL,                                           /* unset_dimension */
     394                 :         NULL,                                           /* get_properties */
     395                 :         NULL,                                           /* get_method */
     396                 :         NULL,                                           /* call_method */
     397                 :         NULL,                                           /* get_constructor */
     398                 :         NULL,                                           /* get_class_entry */
     399                 :         NULL,                                           /* get_class_name */
     400                 :         NULL,                                           /* compare_objects */
     401                 :         NULL,                                           /* cast_object */
     402                 :         NULL,                                           /* count_elements */
     403                 : };
     404                 : 
     405                 : 
     406                 : /*
     407                 :  * Local variables:
     408                 :  * tab-width: 4
     409                 :  * c-basic-offset: 4
     410                 :  * indent-tabs-mode: t
     411                 :  * End:
     412                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:26:54 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.