diff options
Diffstat (limited to 'Zend/zend_objects_API.c')
-rw-r--r-- | Zend/zend_objects_API.c | 125 |
1 files changed, 58 insertions, 67 deletions
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 3e3c8a8005..c5ac9708e5 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -12,21 +12,19 @@ | obtain it through the world-wide-web, please send a note to | | license@zend.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Authors: Andi Gutmans <andi@zend.com> | - | Zeev Suraski <zeev@zend.com> | - | Dmitry Stogov <dmitry@zend.com> | + | Authors: Andi Gutmans <andi@php.net> | + | Zeev Suraski <zeev@php.net> | + | Dmitry Stogov <dmitry@php.net> | +----------------------------------------------------------------------+ */ -/* $Id$ */ - #include "zend.h" #include "zend_globals.h" #include "zend_variables.h" #include "zend_API.h" #include "zend_objects_API.h" -ZEND_API void zend_objects_store_init(zend_objects_store *objects, uint32_t init_size) +ZEND_API void ZEND_FASTCALL zend_objects_store_init(zend_objects_store *objects, uint32_t init_size) { objects->object_buckets = (zend_object **) emalloc(init_size * sizeof(zend_object*)); objects->top = 1; /* Skip 0 so that handles are true */ @@ -35,13 +33,13 @@ ZEND_API void zend_objects_store_init(zend_objects_store *objects, uint32_t init memset(&objects->object_buckets[0], 0, sizeof(zend_object*)); } -ZEND_API void zend_objects_store_destroy(zend_objects_store *objects) +ZEND_API void ZEND_FASTCALL zend_objects_store_destroy(zend_objects_store *objects) { efree(objects->object_buckets); objects->object_buckets = NULL; } -ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects) +ZEND_API void ZEND_FASTCALL zend_objects_store_call_destructors(zend_objects_store *objects) { EG(flags) |= EG_FLAGS_OBJECT_STORE_NO_REUSE; if (objects->top > 1) { @@ -49,15 +47,15 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects) for (i = 1; i < objects->top; i++) { zend_object *obj = objects->object_buckets[i]; if (IS_OBJ_VALID(obj)) { - if (!(GC_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) { - GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; + if (!(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) { + GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED); if (obj->handlers->dtor_obj && (obj->handlers->dtor_obj != zend_objects_destroy_object || obj->ce->destructor)) { - GC_REFCOUNT(obj)++; + GC_ADDREF(obj); obj->handlers->dtor_obj(obj); - GC_REFCOUNT(obj)--; + GC_DELREF(obj); } } } @@ -65,7 +63,7 @@ ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects) } } -ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects) +ZEND_API void ZEND_FASTCALL zend_objects_store_mark_destructed(zend_objects_store *objects) { if (objects->object_buckets && objects->top > 1) { zend_object **obj_ptr = objects->object_buckets + 1; @@ -75,14 +73,14 @@ ZEND_API void zend_objects_store_mark_destructed(zend_objects_store *objects) zend_object *obj = *obj_ptr; if (IS_OBJ_VALID(obj)) { - GC_FLAGS(obj) |= IS_OBJ_DESTRUCTOR_CALLED; + GC_ADD_FLAGS(obj, IS_OBJ_DESTRUCTOR_CALLED); } obj_ptr++; } while (obj_ptr != end); } } -ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects, zend_bool fast_shutdown) +ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_store *objects, zend_bool fast_shutdown) { zend_object **obj_ptr, **end, *obj; @@ -99,12 +97,12 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects obj_ptr--; obj = *obj_ptr; if (IS_OBJ_VALID(obj)) { - if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { - GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; + if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { + GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); if (obj->handlers->free_obj && obj->handlers->free_obj != zend_object_std_dtor) { - GC_REFCOUNT(obj)++; + GC_ADDREF(obj); obj->handlers->free_obj(obj); - GC_REFCOUNT(obj)--; + GC_DELREF(obj); } } } @@ -114,12 +112,12 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects obj_ptr--; obj = *obj_ptr; if (IS_OBJ_VALID(obj)) { - if (!(GC_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { - GC_FLAGS(obj) |= IS_OBJ_FREE_CALLED; + if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { + GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); if (obj->handlers->free_obj) { - GC_REFCOUNT(obj)++; + GC_ADDREF(obj); obj->handlers->free_obj(obj); - GC_REFCOUNT(obj)--; + GC_DELREF(obj); } } } @@ -130,7 +128,7 @@ ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects /* Store objects API */ -ZEND_API void zend_objects_store_put(zend_object *object) +ZEND_API void ZEND_FASTCALL zend_objects_store_put(zend_object *object) { int handle; @@ -153,61 +151,54 @@ ZEND_API void zend_objects_store_put(zend_object *object) EG(objects_store).object_buckets[handle] = object; } -#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle) \ - SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle], EG(objects_store).free_list_head); \ - EG(objects_store).free_list_head = handle; - -ZEND_API void zend_objects_store_del(zend_object *object) /* {{{ */ +ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ */ { + ZEND_ASSERT(GC_REFCOUNT(object) == 0); + + /* GC might have released this object already. */ + if (UNEXPECTED(GC_TYPE(object) == IS_NULL)) { + return; + } + /* Make sure we hold a reference count during the destructor call otherwise, when the destructor ends the storage might be freed when the refcount reaches 0 a second time */ - if (EG(objects_store).object_buckets && - IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle])) { - if (GC_REFCOUNT(object) == 0) { - if (!(GC_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) { - GC_FLAGS(object) |= IS_OBJ_DESTRUCTOR_CALLED; - - if (object->handlers->dtor_obj - && (object->handlers->dtor_obj != zend_objects_destroy_object - || object->ce->destructor)) { - GC_REFCOUNT(object)++; - object->handlers->dtor_obj(object); - GC_REFCOUNT(object)--; - } - } + if (!(OBJ_FLAGS(object) & IS_OBJ_DESTRUCTOR_CALLED)) { + GC_ADD_FLAGS(object, IS_OBJ_DESTRUCTOR_CALLED); + + if (object->handlers->dtor_obj + && (object->handlers->dtor_obj != zend_objects_destroy_object + || object->ce->destructor)) { + GC_ADDREF(object); + object->handlers->dtor_obj(object); + GC_DELREF(object); + } + } - if (GC_REFCOUNT(object) == 0) { - uint32_t handle = object->handle; - void *ptr; - - EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object); - if (!(GC_FLAGS(object) & IS_OBJ_FREE_CALLED)) { - GC_FLAGS(object) |= IS_OBJ_FREE_CALLED; - if (object->handlers->free_obj) { - GC_REFCOUNT(object)++; - object->handlers->free_obj(object); - GC_REFCOUNT(object)--; - } - } - ptr = ((char*)object) - object->handlers->offset; - GC_REMOVE_FROM_BUFFER(object); - efree(ptr); - ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle); + if (GC_REFCOUNT(object) == 0) { + uint32_t handle = object->handle; + void *ptr; + + ZEND_ASSERT(EG(objects_store).object_buckets != NULL); + ZEND_ASSERT(IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle])); + EG(objects_store).object_buckets[handle] = SET_OBJ_INVALID(object); + if (!(OBJ_FLAGS(object) & IS_OBJ_FREE_CALLED)) { + GC_ADD_FLAGS(object, IS_OBJ_FREE_CALLED); + if (object->handlers->free_obj) { + GC_ADDREF(object); + object->handlers->free_obj(object); + GC_DELREF(object); } - } else { - GC_REFCOUNT(object)--; } + ptr = ((char*)object) - object->handlers->offset; + GC_REMOVE_FROM_BUFFER(object); + efree(ptr); + ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle); } } /* }}} */ -ZEND_API zend_object_handlers *zend_get_std_object_handlers(void) -{ - return &std_object_handlers; -} - /* * Local variables: * tab-width: 4 |