Annotation of embedaddon/php/Zend/zend_objects_API.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | Zend Engine                                                          |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1998-2012 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: 
1.1.1.2 ! misho      20: /* $Id$ */
1.1       misho      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: {
                     32:        objects->object_buckets = (zend_object_store_bucket *) emalloc(init_size * sizeof(zend_object_store_bucket));
                     33:        objects->top = 1; /* Skip 0 so that handles are true */
                     34:        objects->size = init_size;
                     35:        objects->free_list_head = -1;
                     36:        memset(&objects->object_buckets[0], 0, sizeof(zend_object_store_bucket));
                     37: }
                     38: 
                     39: ZEND_API void zend_objects_store_destroy(zend_objects_store *objects)
                     40: {
                     41:        efree(objects->object_buckets);
                     42:        objects->object_buckets = NULL;
                     43: }
                     44: 
                     45: ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC)
                     46: {
                     47:        zend_uint i = 1;
                     48: 
                     49:        for (i = 1; i < objects->top ; i++) {
                     50:                if (objects->object_buckets[i].valid) {
                     51:                        struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
                     52: 
                     53:                        if (!objects->object_buckets[i].destructor_called) {
                     54:                                objects->object_buckets[i].destructor_called = 1;
                     55:                                if (obj->dtor && obj->object) {
                     56:                                        obj->refcount++;
                     57:                                        obj->dtor(obj->object, i TSRMLS_CC);
                     58:                                        obj = &objects->object_buckets[i].bucket.obj;
                     59:                                        obj->refcount--;
                     60:                                }
                     61:                        }
                     62:                }
                     63:        }
                     64: }
                     65: 
                     66: ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects TSRMLS_DC)
                     67: {
                     68:        zend_uint i;
                     69: 
                     70:        if (!objects->object_buckets) {
                     71:                return;
                     72:        }
                     73:        for (i = 1; i < objects->top ; i++) {
                     74:                if (objects->object_buckets[i].valid) {
                     75:                        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: {
                     82:        zend_uint i = 1;
                     83: 
                     84:        for (i = 1; i < objects->top ; i++) {
                     85:                if (objects->object_buckets[i].valid) {
                     86:                        struct _store_object *obj = &objects->object_buckets[i].bucket.obj;
                     87: 
                     88:                        GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
                     89: 
                     90:                        objects->object_buckets[i].valid = 0;
                     91:                        if (obj->free_storage) {
                     92:                                obj->free_storage(obj->object TSRMLS_CC);
                     93:                        }
                     94:                        /* Not adding to free list as we are shutting down anyway */
                     95:                }
                     96:        }
                     97: }
                     98: 
                     99: 
                    100: /* Store objects API */
                    101: 
                    102: 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:        if (EG(objects_store).free_list_head != -1) {
                    108:                handle = EG(objects_store).free_list_head;
                    109:                EG(objects_store).free_list_head = EG(objects_store).object_buckets[handle].bucket.free_list.next;
                    110:        } else {
                    111:                if (EG(objects_store).top == EG(objects_store).size) {
                    112:                        EG(objects_store).size <<= 1;
                    113:                        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:                handle = EG(objects_store).top++;
                    116:        }
                    117:        obj = &EG(objects_store).object_buckets[handle].bucket.obj;
                    118:        EG(objects_store).object_buckets[handle].destructor_called = 0;
                    119:        EG(objects_store).object_buckets[handle].valid = 1;
                    120: 
                    121:        obj->refcount = 1;
                    122:        GC_OBJ_INIT(obj);
                    123:        obj->object = object;
                    124:        obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
                    125:        obj->free_storage = free_storage;
                    126:        obj->clone = clone;
                    127:        obj->handlers = NULL;
                    128: 
                    129: #if ZEND_DEBUG_OBJECTS
                    130:        fprintf(stderr, "Allocated object id #%d\n", handle);
                    131: #endif
                    132:        return handle;
                    133: }
                    134: 
                    135: ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC)
                    136: {
                    137:        zend_object_handle handle = Z_OBJ_HANDLE_P(object);
                    138: 
                    139:        return EG(objects_store).object_buckets[handle].bucket.obj.refcount;
                    140: }
                    141: 
                    142: ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC)
                    143: {
                    144:        zend_object_handle handle = Z_OBJ_HANDLE_P(object);
                    145: 
                    146:        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: }
                    151: 
                    152: /*
                    153:  * Add a reference to an objects store entry given the object handle.
                    154:  */
                    155: ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC)
                    156: {
                    157:        EG(objects_store).object_buckets[handle].bucket.obj.refcount++;
                    158: }
                    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: ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC)
                    166: {
                    167:        zend_object_handle handle;
                    168: 
                    169:        handle = Z_OBJ_HANDLE_P(zobject);
                    170: 
                    171:        Z_ADDREF_P(zobject);
                    172:        zend_objects_store_del_ref_by_handle_ex(handle, Z_OBJ_HT_P(zobject) TSRMLS_CC);
                    173:        Z_DELREF_P(zobject);
                    174: 
                    175:        GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject);
                    176: }
                    177: 
                    178: /*
                    179:  * Delete a reference to an objects store entry given the object handle.
                    180:  */
                    181: 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:        int failure = 0;
                    185: 
                    186:        if (!EG(objects_store).object_buckets) {
                    187:                return;
                    188:        }
                    189: 
                    190:        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:        if (EG(objects_store).object_buckets[handle].valid) {
                    197:                if (obj->refcount == 1) {
                    198:                        if (!EG(objects_store).object_buckets[handle].destructor_called) {
                    199:                                EG(objects_store).object_buckets[handle].destructor_called = 1;
                    200: 
                    201:                                if (obj->dtor) {
                    202:                                        if (handlers && !obj->handlers) {
                    203:                                                obj->handlers = handlers;
                    204:                                        }
                    205:                                        zend_try {
                    206:                                                obj->dtor(obj->object, handle TSRMLS_CC);
                    207:                                        } zend_catch {
                    208:                                                failure = 1;
                    209:                                        } 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:                        obj = &EG(objects_store).object_buckets[handle].bucket.obj;
                    215: 
                    216:                        if (obj->refcount == 1) {
                    217:                                GC_REMOVE_ZOBJ_FROM_BUFFER(obj);
                    218:                                if (obj->free_storage) {
                    219:                                        zend_try {
                    220:                                                obj->free_storage(obj->object TSRMLS_CC);
                    221:                                        } zend_catch {
                    222:                                                failure = 1;
                    223:                                        } zend_end_try();
                    224:                                }
                    225:                                ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST();
                    226:                        }
                    227:                }
                    228:        }
                    229: 
                    230:        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:        if (failure) {
                    240:                zend_bailout();
                    241:        }
                    242: }
                    243: /* }}} */
                    244: 
                    245: 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:        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
                    251: 
                    252:        obj = &EG(objects_store).object_buckets[handle].bucket.obj;
                    253: 
                    254:        if (obj->clone == NULL) {
                    255:                zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name);
                    256:        }
                    257: 
                    258:        obj->clone(obj->object, &new_object TSRMLS_CC);
                    259:        obj = &EG(objects_store).object_buckets[handle].bucket.obj;
                    260: 
                    261:        retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->free_storage, obj->clone TSRMLS_CC);
                    262:        retval.handlers = Z_OBJ_HT_P(zobject);
                    263:        EG(objects_store).object_buckets[handle].bucket.obj.handlers = retval.handlers;
                    264: 
                    265:        return retval;
                    266: }
                    267: 
                    268: ZEND_API void *zend_object_store_get_object(const zval *zobject TSRMLS_DC)
                    269: {
                    270:        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
                    271: 
                    272:        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: ZEND_API void *zend_object_store_get_object_by_handle(zend_object_handle handle TSRMLS_DC)
                    279: {
                    280:        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: ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC)
                    291: {
                    292:        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
                    293: 
                    294:        EG(objects_store).object_buckets[handle].bucket.obj.object = object;
                    295: }
                    296: 
                    297: 
                    298: /* Called when the ctor was terminated by an exception */
                    299: ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC)
                    300: {
                    301:        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
                    302:        zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle];
                    303:        
                    304:        obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);;
                    305:        obj_bucket->destructor_called = 1;
                    306: }
                    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: 
1.1.1.2 ! misho     317: ZEND_API void zend_objects_proxy_destroy(zend_object *object, zend_object_handle handle TSRMLS_DC)
        !           318: {
        !           319: }
        !           320: 
1.1       misho     321: ZEND_API void zend_objects_proxy_free_storage(zend_proxy_object *object TSRMLS_DC)
                    322: {
                    323:        zval_ptr_dtor(&object->object);
                    324:        zval_ptr_dtor(&object->property);
                    325:        efree(object);
                    326: }
                    327: 
                    328: ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC)
                    329: {
                    330:        *object_clone = emalloc(sizeof(zend_proxy_object));
                    331:        (*object_clone)->object = object->object;
                    332:        (*object_clone)->property = object->property;
                    333:        zval_add_ref(&(*object_clone)->property);
                    334:        zval_add_ref(&(*object_clone)->object);
                    335: }
                    336: 
                    337: ZEND_API zval *zend_object_create_proxy(zval *object, zval *member TSRMLS_DC)
                    338: {
                    339:        zend_proxy_object *pobj = emalloc(sizeof(zend_proxy_object));
                    340:        zval *retval;
                    341: 
                    342:        pobj->object = object;
                    343:        zval_add_ref(&pobj->object);
1.1.1.2 ! misho     344:        ALLOC_ZVAL(pobj->property);
        !           345:        INIT_PZVAL_COPY(pobj->property, member);
        !           346:        zval_copy_ctor(pobj->property);
1.1       misho     347: 
                    348:        MAKE_STD_ZVAL(retval);
                    349:        Z_TYPE_P(retval) = IS_OBJECT;
1.1.1.2 ! misho     350:        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);
1.1       misho     351:        Z_OBJ_HT_P(retval) = &zend_object_proxy_handlers;
                    352: 
                    353:        return retval;
                    354: }
                    355: 
                    356: ZEND_API void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC)
                    357: {
                    358:        zend_proxy_object *probj = zend_object_store_get_object(*property TSRMLS_CC);
                    359: 
                    360:        if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->write_property) {
1.1.1.2 ! misho     361:                Z_OBJ_HT_P(probj->object)->write_property(probj->object, probj->property, value, 0 TSRMLS_CC);
1.1       misho     362:        } else {
                    363:                zend_error(E_WARNING, "Cannot write property of object - no write handler defined");
                    364:        }
                    365: }
                    366: 
                    367: ZEND_API zval* zend_object_proxy_get(zval *property TSRMLS_DC)
                    368: {
                    369:        zend_proxy_object *probj = zend_object_store_get_object(property TSRMLS_CC);
                    370: 
                    371:        if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->read_property) {
1.1.1.2 ! misho     372:                return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property, BP_VAR_R, 0 TSRMLS_CC);
1.1       misho     373:        } else {
                    374:                zend_error(E_WARNING, "Cannot read property of object - no read handler defined");
                    375:        }
                    376: 
                    377:        return NULL;
                    378: }
                    379: 
                    380: ZEND_API zend_object_handlers *zend_get_std_object_handlers(void)
                    381: {
                    382:        return &std_object_handlers;
                    383: }
                    384: 
                    385: static zend_object_handlers zend_object_proxy_handlers = {
                    386:        ZEND_OBJECTS_STORE_HANDLERS,
                    387: 
                    388:        NULL,                                           /* read_property */
                    389:        NULL,                                           /* write_property */
                    390:        NULL,                                           /* read dimension */
                    391:        NULL,                                           /* write_dimension */
                    392:        NULL,                                           /* get_property_ptr_ptr */
                    393:        zend_object_proxy_get,          /* get */
                    394:        zend_object_proxy_set,          /* set */
                    395:        NULL,                                           /* has_property */
                    396:        NULL,                                           /* unset_property */
                    397:        NULL,                                           /* has_dimension */
                    398:        NULL,                                           /* unset_dimension */
                    399:        NULL,                                           /* get_properties */
                    400:        NULL,                                           /* get_method */
                    401:        NULL,                                           /* call_method */
                    402:        NULL,                                           /* get_constructor */
                    403:        NULL,                                           /* get_class_entry */
                    404:        NULL,                                           /* get_class_name */
                    405:        NULL,                                           /* compare_objects */
                    406:        NULL,                                           /* cast_object */
                    407:        NULL,                                           /* count_elements */
                    408: };
                    409: 
                    410: 
                    411: /*
                    412:  * Local variables:
                    413:  * tab-width: 4
                    414:  * c-basic-offset: 4
                    415:  * indent-tabs-mode: t
                    416:  * End:
                    417:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>