Skip to content

Commit 9e6eab3

Browse files
committedAug 31, 2022
Store default object handlers alongside the class entry
Object handlers being separate from class entries is a legacy inherited from PHP 5. Today it has little benefit to keep them separate: in fact, accessing object handlers usually requires not-so-safe hacks. While it is possible to swap handlers in a custom installed create_object handler, this mostly is tedious, as well as it requires allocating the object handlers struct at runtime, possibly caching it etc.. This allows extensions, which intend to observe other classes to install their own class handlers. The life cycle of internal classes may now be simply observed by swapping the class handlers in post_startup stage. The life cycle of userland classes may be observed by iterating over the new classes in zend_compile_file and zend_compile_string and then swapping their handlers. In general, this would also be a first step in directly tying the object handlers to classes. Especially given that I am not aware of any case where the object handlers would be different between various instances of a given class. Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
1 parent 807fe37 commit 9e6eab3

13 files changed

+35
-58
lines changed
 

‎Zend/zend.h

+2
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ struct _zend_class_entry {
182182
zend_function *__serialize;
183183
zend_function *__unserialize;
184184

185+
const zend_object_handlers *default_object_handlers;
186+
185187
/* allocated only if class implements Iterator or IteratorAggregate interface */
186188
zend_class_iterator_funcs *iterator_funcs_ptr;
187189
/* allocated only if class implements ArrayAccess interface */

‎Zend/zend_API.h

+2
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,13 @@ typedef struct _zend_fcall_info_cache {
272272
{ \
273273
memset(&class_container, 0, sizeof(zend_class_entry)); \
274274
class_container.name = zend_string_init_interned(class_name, class_name_len, 1); \
275+
class_container.default_object_handlers = &std_object_handlers; \
275276
class_container.info.internal.builtin_functions = functions; \
276277
}
277278

278279
#define INIT_CLASS_ENTRY_INIT_METHODS(class_container, functions) \
279280
{ \
281+
class_container.default_object_handlers = &std_object_handlers; \
280282
class_container.constructor = NULL; \
281283
class_container.destructor = NULL; \
282284
class_container.clone = NULL; \

‎Zend/zend_attributes.c

+1-13
Original file line numberDiff line numberDiff line change
@@ -131,18 +131,6 @@ ZEND_METHOD(SensitiveParameterValue, __debugInfo)
131131
RETURN_EMPTY_ARRAY();
132132
}
133133

134-
static zend_object *attributes_sensitive_parameter_value_new(zend_class_entry *ce)
135-
{
136-
zend_object *object;
137-
138-
object = zend_objects_new(ce);
139-
object->handlers = &attributes_object_handlers_sensitive_parameter_value;
140-
141-
object_properties_init(object, ce);
142-
143-
return object;
144-
}
145-
146134
static HashTable *attributes_sensitive_parameter_value_get_properties_for(zend_object *zobj, zend_prop_purpose purpose)
147135
{
148136
return NULL;
@@ -382,7 +370,7 @@ void zend_register_attribute_ce(void)
382370

383371
/* This is not an actual attribute, thus the zend_mark_internal_attribute() call is missing. */
384372
zend_ce_sensitive_parameter_value = register_class_SensitiveParameterValue();
385-
zend_ce_sensitive_parameter_value->create_object = attributes_sensitive_parameter_value_new;
373+
zend_ce_sensitive_parameter_value->default_object_handlers = &attributes_object_handlers_sensitive_parameter_value;
386374
}
387375

388376
void zend_attributes_shutdown(void)

‎Zend/zend_closures.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,6 @@ static zend_object *zend_closure_new(zend_class_entry *class_type) /* {{{ */
521521
memset(closure, 0, sizeof(zend_closure));
522522

523523
zend_object_std_init(&closure->std, class_type);
524-
closure->std.handlers = &closure_handlers;
525524

526525
return (zend_object*)closure;
527526
}
@@ -678,6 +677,7 @@ void zend_register_closure_ce(void) /* {{{ */
678677
{
679678
zend_ce_closure = register_class_Closure();
680679
zend_ce_closure->create_object = zend_closure_new;
680+
zend_ce_closure->default_object_handlers = &closure_handlers;
681681

682682
memcpy(&closure_handlers, &std_object_handlers, sizeof(zend_object_handlers));
683683
closure_handlers.free_obj = zend_closure_free_storage;

‎Zend/zend_compile.c

+1
Original file line numberDiff line numberDiff line change
@@ -1828,6 +1828,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, bool nullify_hand
18281828
ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
18291829
ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
18301830

1831+
ce->default_object_handlers = &std_object_handlers;
18311832
ce->default_properties_count = 0;
18321833
ce->default_static_members_count = 0;
18331834
ce->properties_info_table = NULL;

‎Zend/zend_enum.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ zend_object *zend_enum_new(zval *result, zend_class_entry *ce, zend_string *case
4747
ZVAL_COPY(OBJ_PROP_NUM(zobj, 1), backing_value_zv);
4848
}
4949

50-
zobj->handlers = &enum_handlers;
51-
5250
return zobj;
5351
}
5452

@@ -184,6 +182,8 @@ void zend_enum_add_interfaces(zend_class_entry *ce)
184182
ce->interface_names[num_interfaces_before + 1].name = zend_string_copy(zend_ce_backed_enum->name);
185183
ce->interface_names[num_interfaces_before + 1].lc_name = zend_string_init("backedenum", sizeof("backedenum") - 1, 0);
186184
}
185+
186+
ce->default_object_handlers = &enum_handlers;
187187
}
188188

189189
zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce)

‎Zend/zend_exceptions.c

+18-27
Original file line numberDiff line numberDiff line change
@@ -240,21 +240,19 @@ ZEND_API void zend_clear_exception(void) /* {{{ */
240240
}
241241
/* }}} */
242242

243-
static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type, bool skip_top_traces) /* {{{ */
243+
static zend_object *zend_default_exception_new(zend_class_entry *class_type) /* {{{ */
244244
{
245245
zval tmp;
246246
zval trace;
247247
zend_class_entry *base_ce;
248248
zend_string *filename;
249249

250250
zend_object *object = zend_objects_new(class_type);
251-
object->handlers = &default_exception_handlers;
252-
253251
object_properties_init(object, class_type);
254252

255253
if (EG(current_execute_data)) {
256254
zend_fetch_debug_backtrace(&trace,
257-
skip_top_traces,
255+
0,
258256
EG(exception_ignore_args) ? DEBUG_BACKTRACE_IGNORE_ARGS : 0, 0);
259257
} else {
260258
array_init(&trace);
@@ -282,18 +280,6 @@ static zend_object *zend_default_exception_new_ex(zend_class_entry *class_type,
282280
}
283281
/* }}} */
284282

285-
static zend_object *zend_default_exception_new(zend_class_entry *class_type) /* {{{ */
286-
{
287-
return zend_default_exception_new_ex(class_type, 0);
288-
}
289-
/* }}} */
290-
291-
static zend_object *zend_error_exception_new(zend_class_entry *class_type) /* {{{ */
292-
{
293-
return zend_default_exception_new_ex(class_type, 0);
294-
}
295-
/* }}} */
296-
297283
/* {{{ Clone the exception object */
298284
ZEND_COLD ZEND_METHOD(Exception, __clone)
299285
{
@@ -739,6 +725,11 @@ ZEND_METHOD(Exception, __toString)
739725
}
740726
/* }}} */
741727

728+
static void zend_init_exception_class_entry(zend_class_entry *ce) {
729+
ce->create_object = zend_default_exception_new;
730+
ce->default_object_handlers = &default_exception_handlers;
731+
}
732+
742733
void zend_register_default_exception(void) /* {{{ */
743734
{
744735
zend_ce_throwable = register_class_Throwable(zend_ce_stringable);
@@ -748,37 +739,37 @@ void zend_register_default_exception(void) /* {{{ */
748739
default_exception_handlers.clone_obj = NULL;
749740

750741
zend_ce_exception = register_class_Exception(zend_ce_throwable);
751-
zend_ce_exception->create_object = zend_default_exception_new;
742+
zend_init_exception_class_entry(zend_ce_exception);
752743

753744
zend_ce_error_exception = register_class_ErrorException(zend_ce_exception);
754-
zend_ce_error_exception->create_object = zend_error_exception_new;
745+
zend_init_exception_class_entry(zend_ce_error_exception);
755746

756747
zend_ce_error = register_class_Error(zend_ce_throwable);
757-
zend_ce_error->create_object = zend_default_exception_new;
748+
zend_init_exception_class_entry(zend_ce_error);
758749

759750
zend_ce_compile_error = register_class_CompileError(zend_ce_error);
760-
zend_ce_compile_error->create_object = zend_default_exception_new;
751+
zend_init_exception_class_entry(zend_ce_compile_error);
761752

762753
zend_ce_parse_error = register_class_ParseError(zend_ce_compile_error);
763-
zend_ce_parse_error->create_object = zend_default_exception_new;
754+
zend_init_exception_class_entry(zend_ce_parse_error);
764755

765756
zend_ce_type_error = register_class_TypeError(zend_ce_error);
766-
zend_ce_type_error->create_object = zend_default_exception_new;
757+
zend_init_exception_class_entry(zend_ce_type_error);
767758

768759
zend_ce_argument_count_error = register_class_ArgumentCountError(zend_ce_type_error);
769-
zend_ce_argument_count_error->create_object = zend_default_exception_new;
760+
zend_init_exception_class_entry(zend_ce_argument_count_error);
770761

771762
zend_ce_value_error = register_class_ValueError(zend_ce_error);
772-
zend_ce_value_error->create_object = zend_default_exception_new;
763+
zend_init_exception_class_entry(zend_ce_value_error);
773764

774765
zend_ce_arithmetic_error = register_class_ArithmeticError(zend_ce_error);
775-
zend_ce_arithmetic_error->create_object = zend_default_exception_new;
766+
zend_init_exception_class_entry(zend_ce_arithmetic_error);
776767

777768
zend_ce_division_by_zero_error = register_class_DivisionByZeroError(zend_ce_arithmetic_error);
778-
zend_ce_division_by_zero_error->create_object = zend_default_exception_new;
769+
zend_init_exception_class_entry(zend_ce_division_by_zero_error);
779770

780771
zend_ce_unhandled_match_error = register_class_UnhandledMatchError(zend_ce_error);
781-
zend_ce_unhandled_match_error->create_object = zend_default_exception_new;
772+
zend_init_exception_class_entry(zend_ce_unhandled_match_error);
782773

783774
INIT_CLASS_ENTRY(zend_ce_unwind_exit, "UnwindExit", NULL);
784775

‎Zend/zend_fibers.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -589,12 +589,9 @@ static zend_always_inline zend_fiber_transfer zend_fiber_suspend(zend_fiber *fib
589589
static zend_object *zend_fiber_object_create(zend_class_entry *ce)
590590
{
591591
zend_fiber *fiber = emalloc(sizeof(zend_fiber));
592-
593592
memset(fiber, 0, sizeof(zend_fiber));
594593

595594
zend_object_std_init(&fiber->std, ce);
596-
fiber->std.handlers = &zend_fiber_handlers;
597-
598595
return &fiber->std;
599596
}
600597

@@ -903,6 +900,7 @@ void zend_register_fiber_ce(void)
903900
{
904901
zend_ce_fiber = register_class_Fiber();
905902
zend_ce_fiber->create_object = zend_fiber_object_create;
903+
zend_ce_fiber->default_object_handlers = &zend_fiber_handlers;
906904

907905
zend_fiber_handlers = std_object_handlers;
908906
zend_fiber_handlers.dtor_obj = zend_fiber_object_destroy;

‎Zend/zend_generators.c

+2-5
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,7 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *
404404

405405
static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ */
406406
{
407-
zend_generator *generator;
408-
409-
generator = emalloc(sizeof(zend_generator));
407+
zend_generator *generator = emalloc(sizeof(zend_generator));
410408
memset(generator, 0, sizeof(zend_generator));
411409

412410
/* The key will be incremented on first use, so it'll start at 0 */
@@ -421,8 +419,6 @@ static zend_object *zend_generator_create(zend_class_entry *class_type) /* {{{ *
421419
generator->node.ptr.root = NULL;
422420

423421
zend_object_std_init(&generator->std, class_type);
424-
generator->std.handlers = &zend_generator_handlers;
425-
426422
return (zend_object*)generator;
427423
}
428424
/* }}} */
@@ -1132,6 +1128,7 @@ void zend_register_generator_ce(void) /* {{{ */
11321128
zend_ce_generator->create_object = zend_generator_create;
11331129
/* get_iterator has to be assigned *after* implementing the interface */
11341130
zend_ce_generator->get_iterator = zend_generator_get_iterator;
1131+
zend_ce_generator->default_object_handlers = &zend_generator_handlers;
11351132

11361133
memcpy(&zend_generator_handlers, &std_object_handlers, sizeof(zend_object_handlers));
11371134
zend_generator_handlers.free_obj = zend_generator_free_storage;

‎Zend/zend_interfaces.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,6 @@ typedef struct {
480480
static zend_object *zend_internal_iterator_create(zend_class_entry *ce) {
481481
zend_internal_iterator *intern = emalloc(sizeof(zend_internal_iterator));
482482
zend_object_std_init(&intern->std, ce);
483-
intern->std.handlers = &zend_internal_iterator_handlers;
484483
intern->iter = NULL;
485484
intern->rewind_called = 0;
486485
return &intern->std;
@@ -655,6 +654,7 @@ ZEND_API void zend_register_interfaces(void)
655654

656655
zend_ce_internal_iterator = register_class_InternalIterator(zend_ce_iterator);
657656
zend_ce_internal_iterator->create_object = zend_internal_iterator_create;
657+
zend_ce_internal_iterator->default_object_handlers = &zend_internal_iterator_handlers;
658658

659659
memcpy(&zend_internal_iterator_handlers, zend_get_std_object_handlers(),
660660
sizeof(zend_object_handlers));

‎Zend/zend_objects.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static zend_always_inline void _zend_object_std_init(zend_object *object, zend_c
3131
GC_SET_REFCOUNT(object, 1);
3232
GC_TYPE_INFO(object) = GC_OBJECT;
3333
object->ce = ce;
34+
object->handlers = ce->default_object_handlers;
3435
object->properties = NULL;
3536
zend_objects_store_put(object);
3637
if (UNEXPECTED(ce->ce_flags & ZEND_ACC_USE_GUARDS)) {
@@ -186,7 +187,6 @@ ZEND_API zend_object* ZEND_FASTCALL zend_objects_new(zend_class_entry *ce)
186187
zend_object *object = emalloc(sizeof(zend_object) + zend_object_properties_size(ce));
187188

188189
_zend_object_std_init(object, ce);
189-
object->handlers = &std_object_handlers;
190190
return object;
191191
}
192192

‎Zend/zend_weakrefs.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,6 @@ static zend_object* zend_weakref_new(zend_class_entry *ce) {
210210
zend_weakref *wr = zend_object_alloc(sizeof(zend_weakref), zend_ce_weakref);
211211

212212
zend_object_std_init(&wr->std, zend_ce_weakref);
213-
214-
wr->std.handlers = &zend_weakref_handlers;
215-
216213
return &wr->std;
217214
}
218215

@@ -304,7 +301,6 @@ static zend_object *zend_weakmap_create_object(zend_class_entry *ce)
304301
{
305302
zend_weakmap *wm = zend_object_alloc(sizeof(zend_weakmap), ce);
306303
zend_object_std_init(&wm->std, ce);
307-
wm->std.handlers = &zend_weakmap_handlers;
308304

309305
zend_hash_init(&wm->ht, 0, NULL, ZVAL_PTR_DTOR, 0);
310306
return &wm->std;
@@ -651,6 +647,7 @@ void zend_register_weakref_ce(void) /* {{{ */
651647
zend_ce_weakref = register_class_WeakReference();
652648

653649
zend_ce_weakref->create_object = zend_weakref_new;
650+
zend_ce_weakref->default_object_handlers = &zend_weakref_handlers;
654651

655652
memcpy(&zend_weakref_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
656653
zend_weakref_handlers.offset = XtOffsetOf(zend_weakref, std);
@@ -662,6 +659,7 @@ void zend_register_weakref_ce(void) /* {{{ */
662659

663660
zend_ce_weakmap->create_object = zend_weakmap_create_object;
664661
zend_ce_weakmap->get_iterator = zend_weakmap_get_iterator;
662+
zend_ce_weakmap->default_object_handlers = &zend_weakmap_handlers;
665663

666664
memcpy(&zend_weakmap_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
667665
zend_weakmap_handlers.offset = XtOffsetOf(zend_weakmap, std);

‎ext/dom/php_dom.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ PHP_MINIT_FUNCTION(dom)
782782

783783
dom_xpath_class_entry = register_class_DOMXPath();
784784
dom_xpath_class_entry->create_object = dom_xpath_objects_new;
785+
dom_xpath_class_entry->default_object_handlers = &dom_xpath_object_handlers;
785786

786787
zend_hash_init(&dom_xpath_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
787788
dom_register_prop_handler(&dom_xpath_prop_handlers, "document", sizeof("document")-1, dom_xpath_document_read, NULL);
@@ -989,7 +990,6 @@ zend_object *dom_xpath_objects_new(zend_class_entry *class_type)
989990
intern->register_node_ns = 1;
990991

991992
intern->dom.prop_handler = &dom_xpath_prop_handlers;
992-
intern->dom.std.handlers = &dom_xpath_object_handlers;
993993

994994
zend_object_std_init(&intern->dom.std, class_type);
995995
object_properties_init(&intern->dom.std, class_type);

0 commit comments

Comments
 (0)