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

LCOV - code coverage report
Current view: top level - Zend - zend_objects_API.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 128 167 76.6 %
Date: 2014-04-18 Functions: 16 22 72.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2013 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$ */
      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       19327 : ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size)
      31             : {
      32       19327 :         objects->object_buckets = (zend_object_store_bucket *) emalloc(init_size * sizeof(zend_object_store_bucket));
      33       19327 :         objects->top = 1; /* Skip 0 so that handles are true */
      34       19327 :         objects->size = init_size;
      35       19327 :         objects->free_list_head = -1;
      36       19327 :         memset(&objects->object_buckets[0], 0, sizeof(zend_object_store_bucket));
      37       19327 : }
      38             : 
      39       19362 : ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
      40             : {
      41       19362 :         efree(objects->object_buckets);
      42       19362 :         objects->object_buckets = NULL;
      43       19362 : }
      44             : 
      45       19362 : ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC)
      46             : {
      47       19362 :         zend_uint i = 1;
      48             : 
      49      171905 :         for (i = 1; i < objects->top ; i++) {
      50      152543 :                 if (objects->object_buckets[i].valid) {
      51      127206 :                         struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
      52             : 
      53      127206 :                         if (!objects->object_buckets[i].destructor_called) {
      54      126858 :                                 objects->object_buckets[i].destructor_called = 1;
      55      126858 :                                 if (obj->dtor && obj->object) {
      56      126858 :                                         obj->refcount++;
      57      126858 :                                         obj->dtor(obj->object, i TSRMLS_CC);
      58      126858 :                                         obj = &objects->object_buckets[i].bucket.obj;
      59      126858 :                                         obj->refcount--;
      60             :                                 }
      61             :                         }
      62             :                 }
      63             :         }
      64       19362 : }
      65             : 
      66         593 : ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC)
      67             : {
      68             :         zend_uint i;
      69             : 
      70         593 :         if (!objects->object_buckets) {
      71           5 :                 return;
      72             :         }
      73        1113 :         for (i = 1; i < objects->top ; i++) {
      74         525 :                 if (objects->object_buckets[i].valid) {
      75         470 :                         objects->object_buckets[i].destructor_called = 1;
      76             :                 }
      77             :         }
      78             : }
      79             : 
      80       19362 : ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC)
      81             : {
      82       19362 :         zend_uint i = 1;
      83             : 
      84      171910 :         for (i = 1; i < objects->top ; i++) {
      85      152548 :                 if (objects->object_buckets[i].valid) {
      86        1432 :                         struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
      87             : 
      88        2680 :                         GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
      89             : 
      90        1432 :                         objects->object_buckets[i].valid = 0;
      91        1432 :                         if (obj->free_storage) {
      92        1430 :                                 obj->free_storage(obj->object TSRMLS_CC);
      93             :                         }
      94             :                         /* Not adding to free list as we are shutting down anyway */
      95             :                 }
      96             :         }
      97       19362 : }
      98             : 
      99             : 
     100             : /* Store objects API */
     101             : 
     102     1742611 : 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             : {
     104             :         zend_object_handle handle;
     105             :         struct _store_object *obj;
     106             : 
     107     1742611 :         if (EG(objects_store).free_list_head != -1) {
     108     1590070 :                 handle = EG(objects_store).free_list_head;
     109     1590070 :                 EG(objects_store).free_list_head = EG(objects_store).object_buckets[handle].bucket.free_list.next;
     110             :         } else {
     111      152541 :                 if (EG(objects_store).top == EG(objects_store).size) {
     112          21 :                         EG(objects_store).size <<= 1;
     113          21 :                         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      152541 :                 handle = EG(objects_store).top++;
     116             :         }
     117     1742611 :         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     118     1742611 :         EG(objects_store).object_buckets[handle].destructor_called = 0;
     119     1742611 :         EG(objects_store).object_buckets[handle].valid = 1;
     120             : 
     121     1742611 :         obj->refcount = 1;
     122     1742611 :         GC_OBJ_INIT(obj);
     123     1742611 :         obj->object = object;
     124     1742611 :         obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
     125     1742611 :         obj->free_storage = free_storage;
     126     1742611 :         obj->clone = clone;
     127     1742611 :         obj->handlers = NULL;
     128             : 
     129             : #if ZEND_DEBUG_OBJECTS
     130             :         fprintf(stderr, "Allocated object id #%d\n", handle);
     131             : #endif
     132     1742611 :         return handle;
     133             : }
     134             : 
     135          21 : ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC)
     136             : {
     137          21 :         zend_object_handle handle = Z_OBJ_HANDLE_P(object);
     138             : 
     139          21 :         return EG(objects_store).object_buckets[handle].bucket.obj.refcount;
     140             : }
     141             : 
     142      372044 : ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC)
     143             : {
     144      372044 :         zend_object_handle handle = Z_OBJ_HANDLE_P(object);
     145             : 
     146      372044 :         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      372044 : }
     151             : 
     152             : /*
     153             :  * Add a reference to an objects store entry given the object handle.
     154             :  */
     155           0 : ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC)
     156             : {
     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     2021190 : ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC)
     166             : {
     167             :         zend_object_handle handle;
     168             : 
     169     2021190 :         handle = Z_OBJ_HANDLE_P(zobject);
     170             : 
     171             :         Z_ADDREF_P(zobject);
     172     2021190 :         zend_objects_store_del_ref_by_handle_ex(handle, Z_OBJ_HT_P(zobject) TSRMLS_CC);
     173             :         Z_DELREF_P(zobject);
     174             : 
     175     2021184 :         GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject);
     176     2021184 : }
     177             : 
     178             : /*
     179             :  * Delete a reference to an objects store entry given the object handle.
     180             :  */
     181     2104227 : ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC) /* {{{ */
     182             : {
     183             :         struct _store_object *obj;
     184     2104227 :         int failure = 0;
     185             : 
     186     2104227 :         if (!EG(objects_store).object_buckets) {
     187           2 :                 return;
     188             :         }
     189             : 
     190     2104225 :         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     2104225 :         if (EG(objects_store).object_buckets[handle].valid) {
     197     2104056 :                 if (obj->refcount == 1) {
     198     1741189 :                         if (!EG(objects_store).object_buckets[handle].destructor_called) {
     199     1531947 :                                 EG(objects_store).object_buckets[handle].destructor_called = 1;
     200             : 
     201     1531947 :                                 if (obj->dtor) {
     202     1531947 :                                         if (handlers && !obj->handlers) {
     203     1531941 :                                                 obj->handlers = handlers;
     204             :                                         }
     205     1531947 :                                         zend_try {
     206     1531947 :                                                 obj->dtor(obj->object, handle TSRMLS_CC);
     207           5 :                                         } zend_catch {
     208           5 :                                                 failure = 1;
     209     1531947 :                                         } 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     1741189 :                         obj = &EG(objects_store).object_buckets[handle].bucket.obj;
     215             : 
     216     1741189 :                         if (obj->refcount == 1) {
     217     3021801 :                                 GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
     218     1741185 :                                 if (obj->free_storage) {
     219     1740504 :                                         zend_try {
     220     1740504 :                                                 obj->free_storage(obj->object TSRMLS_CC);
     221           1 :                                         } zend_catch {
     222           1 :                                                 failure = 1;
     223     1740504 :                                         } zend_end_try();
     224             :                                 }
     225     1741185 :                                 ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST();
     226             :                         }
     227             :                 }
     228             :         }
     229             : 
     230     2104225 :         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     2104225 :         if (failure) {
     240           6 :                 zend_bailout();
     241             :         }
     242             : }
     243             : /* }}} */
     244             : 
     245           6 : ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
     246             : {
     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     9329902 : ZEND_API void *zend_object_store_get_object(const zval *zobject TSRMLS_DC)
     269             : {
     270     9329902 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     271             : 
     272     9329902 :         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           9 : ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle TSRMLS_DC)
     279             : {
     280           9 :         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          32 : ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC)
     291             : {
     292          32 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     293             : 
     294          32 :         EG(objects_store).object_buckets[handle].bucket.obj.object = object;
     295          32 : }
     296             : 
     297             : 
     298             : /* Called when the ctor was terminated by an exception */
     299         310 : ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC)
     300             : {
     301         310 :         zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
     302         310 :         zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle];
     303             :         
     304         310 :         obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);;
     305         310 :         obj_bucket->destructor_called = 1;
     306         310 : }
     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           0 : ZEND_API void zend_objects_proxy_free_storage(zend_proxy_object *object TSRMLS_DC)
     318             : {
     319           0 :         zval_ptr_dtor(&object->object);
     320           0 :         zval_ptr_dtor(&object->property);
     321           0 :         efree(object);
     322           0 : }
     323             : 
     324           0 : ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC)
     325             : {
     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           0 : ZEND_API zval *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC)
     334             : {
     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           0 : ZEND_API void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC)
     352             : {
     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           0 : ZEND_API zval* zend_object_proxy_get(zval *property TSRMLS_DC)
     363             : {
     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      812657 : ZEND_API zend_object_handlers *zend_get_std_object_handlers(void)
     376             : {
     377      812657 :         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: LCOV version 1.10

Generated at Fri, 18 Apr 2014 07:01:22 +0000 (19 hours ago)

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