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: 131 173 75.7 %
Date: 2014-04-10 Functions: 16 23 69.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 10 Apr 2014 08:53:47 +0000 (6 days ago)

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