- Try to get the old copying behavior of objects to work (doesn't work yet).
typedef unsigned int zend_object_handle;
+typedef struct _zend_object_handlers zend_object_handlers;
+
+typedef struct _zend_object_value {
+ zend_object_handle handle;
+ zend_object_handlers *handlers;
+} zend_object_value;
+
typedef zend_object *(*get_address_t)(zend_object_handle handle); /* Don't return zval ** so that we can't change it */
typedef zval **(*get_property_address_t)(zend_object_handle handle, zval *offset, int type);
typedef void (*add_ref_t)(zend_object_handle handle);
typedef void (*del_ref_t)(zend_object_handle handle);
typedef void (*delete_obj_t)(zend_object_handle handle);
+typedef zend_object_value (*clone_obj_t)(zend_object_handle handle);
typedef struct _zend_object_handlers {
get_address_t get_address;
add_ref_t add_ref;
del_ref_t del_ref;
delete_obj_t delete_obj;
+ clone_obj_t clone_obj;
} zend_object_handlers;
-typedef struct _zend_object_value {
- zend_object_handle handle;
- zend_object_handlers handlers;
-} zend_object_value;
-
#include "zend_objects.h"
typedef union _zvalue_value {
if (Ts[node->u.var].var.ptr_ptr) {
PZVAL_UNLOCK(*Ts[node->u.var].var.ptr_ptr);
*should_free = 0;
- SEPARATE_ZVAL_IF_NOT_REF(Ts[node->u.var].var.ptr_ptr);
return *Ts[node->u.var].var.ptr_ptr;
} else {
if (Ts[node->u.var].EA.type==IS_STRING_OFFSET) {
if (Z_TYPE_PP(object) != IS_OBJECT) {
zend_error(E_ERROR, "Cannot call delete on non-object type");
}
- (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
+ (*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
}
zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1);
if (Z_TYPE_PP(object) != IS_OBJECT) {
zend_error(E_ERROR, "Cannot call delete on non-object type");
}
- (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
+ (*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
}
zend_hash_index_del(ht, index);
if (Z_TYPE_PP(object) != IS_OBJECT) {
zend_error(E_ERROR, "Cannot call delete on non-object type");
}
- (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
+ (*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
}
zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1);
if (Z_TYPE_PP(object) != IS_OBJECT) {
zend_error(E_ERROR, "Cannot call delete on non-object type");
}
- (*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
+ (*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
}
zend_hash_del(ht, "", sizeof(""));
}
object_zval = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
- object = object_zval->value.obj.handlers.get_address(object_zval->value.obj.handle);
+ object = object_zval->value.obj.handlers->get_address(object_zval->value.obj.handle);
if (!object->ce->handle_function_call
&& !zend_hash_exists(&object->ce->function_table, object->ce->name, object->ce->name_length+1)) {
NULL,
zend_objects_add_ref,
zend_objects_del_ref,
- zend_objects_delete_obj
+ zend_objects_delete_obj,
+ zend_objects_clone_obj
};
void zend_objects_init(zend_objects *objects, zend_uint init_size)
(*object)->ce = class_type;
retval.handle = handle;
- retval.handlers = zoh;
+ retval.handlers = &zoh;
#if ZEND_DEBUG_OBJECTS
fprintf(stderr, "Allocated object id #%d\n", handle);
#endif
}
#endif
}
+
+zend_object_value zend_objects_clone_obj(zend_object_handle handle)
+{
+ zend_object_value retval;
+ zend_object *old_object;
+ zend_object *new_object;
+
+ TSRMLS_FETCH();
+
+ if (!EG(objects).object_buckets[handle].valid) {
+ zend_error(E_ERROR, "Trying to clone invalid object");
+ }
+
+ old_object = &EG(objects).object_buckets[handle].bucket.obj.object;
+ retval = zend_objects_new(&new_object, old_object->ce);
+ ALLOC_HASHTABLE(new_object->properties);
+ zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
+
+#if ZEND_DEBUG_OBJECTS
+ fprintf(stderr, "Allocated object id #%d\n", handle);
+#endif
+ return retval;
+}
void zend_objects_add_ref(zend_object_handle handle);
void zend_objects_del_ref(zend_object_handle handle);
void zend_objects_delete_obj(zend_object_handle handle);
+zend_object_value zend_objects_clone_obj(zend_object_handle handle);
#endif /* ZEND_OBJECTS_H */
\ No newline at end of file
case IS_ARRAY:
return;
break;
-/* OBJECTS_FIXME */
+/* OBJECTS_OPTIMIZE */
case IS_OBJECT:
- op->type = IS_ARRAY;
- op->value.ht = Z_OBJPROP_P(op);
+ {
+ zval *tmp;
+ HashTable *ht;
+
+ ALLOC_HASHTABLE(ht);
+ zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_copy(ht, Z_OBJPROP_P(op), (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+ zval_dtor(op);
+ op->type = IS_ARRAY;
+ op->value.ht = ht;
+ }
return;
case IS_NULL:
ALLOC_HASHTABLE(op->value.ht);
}
break;
case IS_OBJECT:
-/* OBJECTS_FIXME */
if (Z_OBJCE_P(op1) != Z_OBJCE_P(op2)) {
result->value.lval = 0;
} else {
ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
{
-/* OBJECTS_FIXME */
if (Z_OBJCE_P(o1) != Z_OBJCE_P(o2)) {
result->value.lval = 1; /* Comparing objects of different types is pretty much meaningless */
result->type = IS_LONG;
#define Z_STRVAL(zval) (zval).value.str.val
#define Z_STRLEN(zval) (zval).value.str.len
#define Z_ARRVAL(zval) (zval).value.ht
-#define Z_OBJ(zval) (zval).value.obj.handlers.get_address((zval).value.obj.handle)
+#define Z_OBJ(zval) (zval).value.obj.handlers->get_address((zval).value.obj.handle)
#define Z_OBJPROP(zval) Z_OBJ(zval)->properties
#define Z_OBJCE(zval) Z_OBJ(zval)->ce
#define Z_RESVAL(zval) (zval).value.lval
}
break;
case IS_OBJECT:
- zvalue->value.obj.handlers.del_ref(zvalue->value.obj.handle);
+ zvalue->value.obj.handlers->del_ref(zvalue->value.obj.handle);
break;
case IS_RESOURCE: {
TSRMLS_FETCH();
}
break;
case IS_OBJECT:
- zvalue->value.obj.handlers.add_ref(zvalue->value.obj.handle);
+#if 0
+ zvalue->value.obj = zvalue->value.obj.handlers->clone_obj(zvalue->value.obj.handle);
+#else
+ zvalue->value.obj.handlers->add_ref(zvalue->value.obj.handle);
+#endif
break;
}
return SUCCESS;
zend_hash_apply(zvalue->value.ht, (apply_func_t) zval_persist TSRMLS_CC);
break;
case IS_OBJECT:
- persist_alloc(zvalue->value.obj.properties);
- zend_hash_apply(zvalue->value.obj.properties, (apply_func_t) zval_persist TSRMLS_CC);
+ return FAILURE; /* objects cannot be persisted */
break;
}
return SUCCESS;