Skip to content

Commit ea48c0c

Browse files
author
Andi Gutmans
committed
- Fix a bug in method calls.
- Try to get the old copying behavior of objects to work (doesn't work yet).
1 parent 3510482 commit ea48c0c

File tree

7 files changed

+62
-23
lines changed

7 files changed

+62
-23
lines changed

Zend/zend.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,25 +177,29 @@ typedef struct _zend_object {
177177

178178
typedef unsigned int zend_object_handle;
179179

180+
typedef struct _zend_object_handlers zend_object_handlers;
181+
182+
typedef struct _zend_object_value {
183+
zend_object_handle handle;
184+
zend_object_handlers *handlers;
185+
} zend_object_value;
186+
180187
typedef zend_object *(*get_address_t)(zend_object_handle handle); /* Don't return zval ** so that we can't change it */
181188
typedef zval **(*get_property_address_t)(zend_object_handle handle, zval *offset, int type);
182189
typedef void (*add_ref_t)(zend_object_handle handle);
183190
typedef void (*del_ref_t)(zend_object_handle handle);
184191
typedef void (*delete_obj_t)(zend_object_handle handle);
192+
typedef zend_object_value (*clone_obj_t)(zend_object_handle handle);
185193

186194
typedef struct _zend_object_handlers {
187195
get_address_t get_address;
188196
get_property_address_t get_property_address;
189197
add_ref_t add_ref;
190198
del_ref_t del_ref;
191199
delete_obj_t delete_obj;
200+
clone_obj_t clone_obj;
192201
} zend_object_handlers;
193202

194-
typedef struct _zend_object_value {
195-
zend_object_handle handle;
196-
zend_object_handlers handlers;
197-
} zend_object_value;
198-
199203
#include "zend_objects.h"
200204

201205
typedef union _zvalue_value {

Zend/zend_execute.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ static inline zval *_get_object_zval_ptr(znode *node, temp_variable *Ts, int *sh
139139
if (Ts[node->u.var].var.ptr_ptr) {
140140
PZVAL_UNLOCK(*Ts[node->u.var].var.ptr_ptr);
141141
*should_free = 0;
142-
SEPARATE_ZVAL_IF_NOT_REF(Ts[node->u.var].var.ptr_ptr);
143142
return *Ts[node->u.var].var.ptr_ptr;
144143
} else {
145144
if (Ts[node->u.var].EA.type==IS_STRING_OFFSET) {
@@ -2185,7 +2184,7 @@ binary_assign_op_addr: {
21852184
if (Z_TYPE_PP(object) != IS_OBJECT) {
21862185
zend_error(E_ERROR, "Cannot call delete on non-object type");
21872186
}
2188-
(*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
2187+
(*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
21892188
}
21902189

21912190
zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1);
@@ -2240,7 +2239,7 @@ binary_assign_op_addr: {
22402239
if (Z_TYPE_PP(object) != IS_OBJECT) {
22412240
zend_error(E_ERROR, "Cannot call delete on non-object type");
22422241
}
2243-
(*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
2242+
(*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
22442243
}
22452244

22462245
zend_hash_index_del(ht, index);
@@ -2254,7 +2253,7 @@ binary_assign_op_addr: {
22542253
if (Z_TYPE_PP(object) != IS_OBJECT) {
22552254
zend_error(E_ERROR, "Cannot call delete on non-object type");
22562255
}
2257-
(*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
2256+
(*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
22582257
}
22592258

22602259
zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1);
@@ -2267,7 +2266,7 @@ binary_assign_op_addr: {
22672266
if (Z_TYPE_PP(object) != IS_OBJECT) {
22682267
zend_error(E_ERROR, "Cannot call delete on non-object type");
22692268
}
2270-
(*object)->value.obj.handlers.delete_obj((*object)->value.obj.handle);
2269+
(*object)->value.obj.handlers->delete_obj((*object)->value.obj.handle);
22712270
}
22722271

22732272
zend_hash_del(ht, "", sizeof(""));
@@ -2373,7 +2372,7 @@ binary_assign_op_addr: {
23732372
}
23742373

23752374
object_zval = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
2376-
object = object_zval->value.obj.handlers.get_address(object_zval->value.obj.handle);
2375+
object = object_zval->value.obj.handlers->get_address(object_zval->value.obj.handle);
23772376

23782377
if (!object->ce->handle_function_call
23792378
&& !zend_hash_exists(&object->ce->function_table, object->ce->name, object->ce->name_length+1)) {

Zend/zend_objects.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ static zend_object_handlers zoh = {
99
NULL,
1010
zend_objects_add_ref,
1111
zend_objects_del_ref,
12-
zend_objects_delete_obj
12+
zend_objects_delete_obj,
13+
zend_objects_clone_obj
1314
};
1415

1516
void zend_objects_init(zend_objects *objects, zend_uint init_size)
@@ -50,7 +51,7 @@ zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class
5051
(*object)->ce = class_type;
5152

5253
retval.handle = handle;
53-
retval.handlers = zoh;
54+
retval.handlers = &zoh;
5455
#if ZEND_DEBUG_OBJECTS
5556
fprintf(stderr, "Allocated object id #%d\n", handle);
5657
#endif
@@ -125,3 +126,27 @@ void zend_objects_del_ref(zend_object_handle handle)
125126
}
126127
#endif
127128
}
129+
130+
zend_object_value zend_objects_clone_obj(zend_object_handle handle)
131+
{
132+
zend_object_value retval;
133+
zend_object *old_object;
134+
zend_object *new_object;
135+
136+
TSRMLS_FETCH();
137+
138+
if (!EG(objects).object_buckets[handle].valid) {
139+
zend_error(E_ERROR, "Trying to clone invalid object");
140+
}
141+
142+
old_object = &EG(objects).object_buckets[handle].bucket.obj.object;
143+
retval = zend_objects_new(&new_object, old_object->ce);
144+
ALLOC_HASHTABLE(new_object->properties);
145+
zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
146+
zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
147+
148+
#if ZEND_DEBUG_OBJECTS
149+
fprintf(stderr, "Allocated object id #%d\n", handle);
150+
#endif
151+
return retval;
152+
}

Zend/zend_objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ zend_object *zend_objects_get_address(zend_object_handle handle);
3030
void zend_objects_add_ref(zend_object_handle handle);
3131
void zend_objects_del_ref(zend_object_handle handle);
3232
void zend_objects_delete_obj(zend_object_handle handle);
33+
zend_object_value zend_objects_clone_obj(zend_object_handle handle);
3334

3435
#endif /* ZEND_OBJECTS_H */

Zend/zend_operators.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,19 @@ ZEND_API void convert_to_array(zval *op)
514514
case IS_ARRAY:
515515
return;
516516
break;
517-
/* OBJECTS_FIXME */
517+
/* OBJECTS_OPTIMIZE */
518518
case IS_OBJECT:
519-
op->type = IS_ARRAY;
520-
op->value.ht = Z_OBJPROP_P(op);
519+
{
520+
zval *tmp;
521+
HashTable *ht;
522+
523+
ALLOC_HASHTABLE(ht);
524+
zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
525+
zend_hash_copy(ht, Z_OBJPROP_P(op), (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
526+
zval_dtor(op);
527+
op->type = IS_ARRAY;
528+
op->value.ht = ht;
529+
}
521530
return;
522531
case IS_NULL:
523532
ALLOC_HASHTABLE(op->value.ht);
@@ -1240,7 +1249,6 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
12401249
}
12411250
break;
12421251
case IS_OBJECT:
1243-
/* OBJECTS_FIXME */
12441252
if (Z_OBJCE_P(op1) != Z_OBJCE_P(op2)) {
12451253
result->value.lval = 0;
12461254
} else {
@@ -1695,7 +1703,6 @@ ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC)
16951703

16961704
ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
16971705
{
1698-
/* OBJECTS_FIXME */
16991706
if (Z_OBJCE_P(o1) != Z_OBJCE_P(o2)) {
17001707
result->value.lval = 1; /* Comparing objects of different types is pretty much meaningless */
17011708
result->type = IS_LONG;

Zend/zend_operators.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ ZEND_API int zend_atoi(const char *str, int str_len);
232232
#define Z_STRVAL(zval) (zval).value.str.val
233233
#define Z_STRLEN(zval) (zval).value.str.len
234234
#define Z_ARRVAL(zval) (zval).value.ht
235-
#define Z_OBJ(zval) (zval).value.obj.handlers.get_address((zval).value.obj.handle)
235+
#define Z_OBJ(zval) (zval).value.obj.handlers->get_address((zval).value.obj.handle)
236236
#define Z_OBJPROP(zval) Z_OBJ(zval)->properties
237237
#define Z_OBJCE(zval) Z_OBJ(zval)->ce
238238
#define Z_RESVAL(zval) (zval).value.lval

Zend/zend_variables.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ ZEND_API void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
5454
}
5555
break;
5656
case IS_OBJECT:
57-
zvalue->value.obj.handlers.del_ref(zvalue->value.obj.handle);
57+
zvalue->value.obj.handlers->del_ref(zvalue->value.obj.handle);
5858
break;
5959
case IS_RESOURCE: {
6060
TSRMLS_FETCH();
@@ -119,7 +119,11 @@ ZEND_API int _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
119119
}
120120
break;
121121
case IS_OBJECT:
122-
zvalue->value.obj.handlers.add_ref(zvalue->value.obj.handle);
122+
#if 0
123+
zvalue->value.obj = zvalue->value.obj.handlers->clone_obj(zvalue->value.obj.handle);
124+
#else
125+
zvalue->value.obj.handlers->add_ref(zvalue->value.obj.handle);
126+
#endif
123127
break;
124128
}
125129
return SUCCESS;
@@ -152,8 +156,7 @@ ZEND_API int zval_persist(zval *zvalue TSRMLS_DC)
152156
zend_hash_apply(zvalue->value.ht, (apply_func_t) zval_persist TSRMLS_CC);
153157
break;
154158
case IS_OBJECT:
155-
persist_alloc(zvalue->value.obj.properties);
156-
zend_hash_apply(zvalue->value.obj.properties, (apply_func_t) zval_persist TSRMLS_CC);
159+
return FAILURE; /* objects cannot be persisted */
157160
break;
158161
}
159162
return SUCCESS;

0 commit comments

Comments
 (0)