LTP GCOV extension - code coverage report
Current view: directory - Zend - zend_objects_API.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 156
Code covered: 55.8 % Executed lines: 87
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5