summaryrefslogtreecommitdiff
path: root/Zend/zend_objects.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_objects.c')
-rw-r--r--Zend/zend_objects.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
new file mode 100644
index 0000000000..2380f778fc
--- /dev/null
+++ b/Zend/zend_objects.c
@@ -0,0 +1,122 @@
+#include "zend.h"
+#include "zend_globals.h"
+
+#define ZEND_DEBUG_OBJECTS 0
+
+static zend_object_handlers zoh = {
+ zend_objects_get_address,
+ NULL,
+ zend_objects_add_ref,
+ zend_objects_del_ref,
+ zend_objects_delete_obj
+};
+
+void zend_objects_init(zend_objects *objects, zend_uint init_size)
+{
+ objects->object_buckets = (zend_object_bucket *) emalloc(init_size * sizeof(zend_object_bucket));
+ objects->top = 1; /* Skip 0 so that handles are true */
+ objects->size = init_size;
+ objects->free_list_head = -1;
+}
+
+void zend_objects_destroy(zend_objects *objects)
+{
+ efree(objects->object_buckets);
+}
+
+zend_object_value zend_objects_new(zend_object **object)
+{
+ TSRMLS_FETCH();
+
+ zend_object_handle handle;
+ zend_object_value retval;
+
+ if (EG(objects).free_list_head != -1) {
+ handle = EG(objects).free_list_head;
+ EG(objects).free_list_head = EG(objects).object_buckets[handle].bucket.free_list.next;
+ } else {
+ if (EG(objects).top == EG(objects).size) {
+ EG(objects).size <<= 1;
+ EG(objects).object_buckets = (zend_object_bucket *) erealloc(EG(objects).object_buckets, EG(objects).size * sizeof(zend_object_bucket));
+ }
+ handle = EG(objects).top++;
+ }
+ EG(objects).object_buckets[handle].valid = 1;
+ EG(objects).object_buckets[handle].bucket.obj.refcount = 1;
+ *object = &EG(objects).object_buckets[handle].bucket.obj.object;
+ retval.handle = handle;
+ retval.handlers = zoh;
+#if ZEND_DEBUG_OBJECTS
+ fprintf(stderr, "Allocated object id #%d\n", handle);
+#endif
+ return retval;
+}
+
+zend_object *zend_objects_get_address(zend_object_handle handle)
+{
+ TSRMLS_FETCH();
+
+ if (!EG(objects).object_buckets[handle].valid) {
+ zend_error(E_ERROR, "Trying to access invalid object");
+ }
+ return &EG(objects).object_buckets[handle].bucket.obj.object;
+}
+
+void zend_objects_add_ref(zend_object_handle handle)
+{
+ TSRMLS_FETCH();
+
+ if (!EG(objects).object_buckets[handle].valid) {
+ zend_error(E_ERROR, "Trying to add reference to invalid object");
+ }
+
+ EG(objects).object_buckets[handle].bucket.obj.refcount++;
+#if ZEND_DEBUG_OBJECTS
+ fprintf(stderr, "Increased refcount of object id #%d\n", handle);
+#endif
+}
+
+void zend_objects_delete_obj(zend_object_handle handle)
+{
+ zend_object *object;
+ TSRMLS_FETCH();
+
+ if (!EG(objects).object_buckets[handle].valid) {
+ zend_error(E_ERROR, "Trying to delete invalid object");
+ }
+
+ object = &EG(objects).object_buckets[handle].bucket.obj.object;
+ zend_hash_destroy(object->properties);
+ efree(object->properties);
+ EG(objects).object_buckets[handle].valid = 0;
+#if ZEND_DEBUG_OBJECTS
+ fprintf(stderr, "Deleted object id #%d\n", handle);
+#endif
+
+}
+
+void zend_objects_del_ref(zend_object_handle handle)
+{
+ TSRMLS_FETCH();
+
+ if (--EG(objects).object_buckets[handle].bucket.obj.refcount == 0) {
+ zend_object *object;
+
+ if (EG(objects).object_buckets[handle].valid) {
+ object = &EG(objects).object_buckets[handle].bucket.obj.object;
+ zend_hash_destroy(object->properties);
+ efree(object->properties);
+ }
+ EG(objects).object_buckets[handle].bucket.free_list.next = EG(objects).free_list_head;
+ EG(objects).free_list_head = handle;
+ EG(objects).object_buckets[handle].valid = 0;
+#if ZEND_DEBUG_OBJECTS
+ fprintf(stderr, "Deallocated object id #%d\n", handle);
+#endif
+ }
+#if ZEND_DEBUG_OBJECTS
+ else {
+ fprintf(stderr, "Decreased refcount of object id #%d\n", handle);
+ }
+#endif
+}