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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:25 +0000 (36 hours ago)

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