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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:04 +0000 (5 days ago)

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