php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_lazy_objects.c
Go to the documentation of this file.
1/*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Arnaud Le Blanc <arnaud.lb@gmail.com> |
16 +----------------------------------------------------------------------+
17*/
18
19/* Lazy objects are standard zend_object whose initialization is deferred until
20 * one of their properties backing store is accessed for the first time.
21 *
22 * This is implemented by using the same fallback mechanism as __get and __set
23 * magic methods that is triggered when an undefined property is accessed.
24 *
25 * Execution of methods or virtual property hooks do not trigger initialization
26 * until they access properties.
27 *
28 * A lazy object can be created via the Reflection API. The user specifies an
29 * initializer function that is called when initialization is required.
30 *
31 * There are two kinds of lazy objects:
32 *
33 * - Ghosts: These are initialized in-place by the initializer function
34 * - Proxy: The initializer returns a new instance. After initialization,
35 * interaction with the proxy object are proxied to the instance.
36 *
37 * Internal objects are not supported.
38 */
39
40#include "zend_API.h"
41#include "zend_compile.h"
42#include "zend_execute.h"
43#include "zend_gc.h"
44#include "zend_hash.h"
46#include "zend_objects_API.h"
47#include "zend_operators.h"
48#include "zend_types.h"
49#include "zend_variables.h"
50#include "zend_lazy_objects.h"
51
57typedef struct _zend_lazy_object_info {
58 union {
59 struct {
61 zval zv; /* ReflectionClass::getLazyInitializer() */
63 zend_object *instance; /* For initialized lazy proxy objects */
64 } u;
68
69/* zend_hash dtor_func_t for zend_lazy_objects_store.infos */
70static void zend_lazy_object_info_dtor_func(zval *pElement)
71{
73
76 zend_object_release(info->u.instance);
77 } else {
79 zend_fcc_dtor(&info->u.initializer.fcc);
80 }
81
82 efree(info);
83}
84
86{
87 zend_hash_init(&store->infos, 8, NULL, zend_lazy_object_info_dtor_func, false);
88}
89
91{
92 ZEND_ASSERT(zend_hash_num_elements(&store->infos) == 0 || CG(unclean_shutdown));
93 zend_hash_destroy(&store->infos);
94}
95
96static void zend_lazy_object_set_info(zend_object *obj, zend_lazy_object_info *info)
97{
98 ZEND_ASSERT(zend_object_is_lazy(obj));
99
100 zval *zv = zend_hash_index_add_new_ptr(&EG(lazy_objects_store).infos, obj->handle, info);
102 (void)zv;
103}
104
105static zend_lazy_object_info* zend_lazy_object_get_info(zend_object *obj)
106{
107 ZEND_ASSERT(zend_object_is_lazy(obj));
108
109 zend_lazy_object_info *info = zend_hash_index_find_ptr(&EG(lazy_objects_store).infos, obj->handle);
110 ZEND_ASSERT(info);
111
112 return info;
113}
114
115static bool zend_lazy_object_has_stale_info(zend_object *obj)
116{
117 return zend_hash_index_find_ptr(&EG(lazy_objects_store).infos, obj->handle);
118}
119
121{
122 ZEND_ASSERT(!zend_lazy_object_initialized(obj));
123
124 zend_lazy_object_info *info = zend_lazy_object_get_info(obj);
125
127
128 return &info->u.initializer.zv;
129}
130
131static zend_fcall_info_cache* zend_lazy_object_get_initializer_fcc(zend_object *obj)
132{
133 ZEND_ASSERT(!zend_lazy_object_initialized(obj));
134
135 zend_lazy_object_info *info = zend_lazy_object_get_info(obj);
136
138
139 return &info->u.initializer.fcc;
140}
141
143{
144 ZEND_ASSERT(zend_lazy_object_initialized(obj));
145
146 if (zend_object_is_lazy_proxy(obj)) {
147 zend_lazy_object_info *info = zend_lazy_object_get_info(obj);
148
150
151 return info->u.instance;
152 }
153
154 return obj;
155}
156
158{
159 return zend_lazy_object_get_info(obj)->flags;
160}
161
163{
164 zend_result res = zend_hash_index_del(&EG(lazy_objects_store).infos, obj->handle);
166}
167
169{
170 ZEND_ASSERT(zend_object_is_lazy(obj));
171 ZEND_ASSERT(!zend_lazy_object_initialized(obj));
172
173 zend_lazy_object_info *info = zend_lazy_object_get_info(obj);
174
176
177 info->lazy_properties_count--;
178
179 return info->lazy_properties_count == 0;
180}
181
185
187{
188 /* Internal classes are not supported */
190 return false;
191 }
192
193 for (zend_class_entry *parent = ce->parent; parent; parent = parent->parent) {
194 if (UNEXPECTED(parent->type == ZEND_INTERNAL_CLASS && parent != zend_standard_class_def)) {
195 return false;
196 }
197 }
198
199 return true;
200}
201
202static int zlo_hash_remove_dyn_props_func(zval *pDest)
203{
204 if (Z_TYPE_P(pDest) == IS_INDIRECT) {
206 }
207
209}
210
211static bool zlo_is_iterating(zend_object *object)
212{
213 if (object->properties && HT_ITERATORS_COUNT(object->properties)) {
214 return true;
215 }
216 if (zend_object_is_lazy_proxy(object)
217 && zend_lazy_object_initialized(object)) {
218 return zlo_is_iterating(zend_lazy_object_get_instance(object));
219 }
220 return false;
221}
222
223/* Make object 'obj' lazy. If 'obj' is NULL, create a lazy instance of
224 * class 'reflection_ce' */
226 zend_class_entry *reflection_ce, zval *initializer_zv,
228{
232
233 ZEND_ASSERT(!obj || (!zend_object_is_lazy(obj) || zend_lazy_object_initialized(obj)));
234 ZEND_ASSERT(!obj || instanceof_function(obj->ce, reflection_ce));
235
236 /* Internal classes are not supported */
237 if (UNEXPECTED(reflection_ce->type == ZEND_INTERNAL_CLASS && reflection_ce != zend_standard_class_def)) {
238 zend_throw_error(NULL, "Cannot make instance of internal class lazy: %s is internal", ZSTR_VAL(reflection_ce->name));
239 return NULL;
240 }
241
242 for (zend_class_entry *parent = reflection_ce->parent; parent; parent = parent->parent) {
243 if (UNEXPECTED(parent->type == ZEND_INTERNAL_CLASS && parent != zend_standard_class_def)) {
244 zend_throw_error(NULL, "Cannot make instance of internal class lazy: %s inherits internal class %s",
245 ZSTR_VAL(reflection_ce->name), ZSTR_VAL(parent->name));
246 return NULL;
247 }
248 }
249
250 int lazy_properties_count = 0;
251
252 if (!obj) {
253 if (UNEXPECTED(reflection_ce->ce_flags & ZEND_ACC_UNINSTANTIABLE)) {
254 zval zobj;
255 /* Call object_init_ex() for the generated exception */
256 zend_result result = object_init_ex(&zobj, reflection_ce);
258 (void)result;
259 return NULL;
260 }
261
262 if (UNEXPECTED(!(reflection_ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
263 if (UNEXPECTED(zend_update_class_constants(reflection_ce) != SUCCESS)) {
265 return NULL;
266 }
267 }
268
269 obj = zend_objects_new(reflection_ce);
270
271 /* Iterate in reverse to avoid overriding Z_PROP_FLAG_P() of child props with added hooks (GH-17870). */
272 for (int i = obj->ce->default_properties_count - 1; i >= 0; i--) {
273 zval *p = &obj->properties_table[i];
274 ZVAL_UNDEF(p);
275 Z_PROP_FLAG_P(p) = 0;
276
278 if (prop_info) {
281 lazy_properties_count++;
282 }
283 }
284 } else {
285 if (zlo_is_iterating(obj)) {
286 zend_throw_error(NULL, "Can not reset an object during property iteration");
287 return NULL;
288 }
289 if (zend_object_is_lazy(obj)) {
290 ZEND_ASSERT(zend_object_is_lazy_proxy(obj) && zend_lazy_object_initialized(obj));
293 } else {
294 if (zend_lazy_object_has_stale_info(obj)) {
295 zend_throw_error(NULL, "Can not reset an object while it is being initialized");
296 return NULL;
297 }
298
300 && !(OBJ_FLAGS(obj) & IS_OBJ_DESTRUCTOR_CALLED)) {
302 || obj->ce->destructor) {
304 GC_ADDREF(obj);
305 obj->handlers->dtor_obj(obj);
306 GC_DELREF(obj);
307 if (EG(exception)) {
308 return NULL;
309 }
310 }
311 }
312 }
313
315
316 /* unset() dynamic properties. Do not NULL out obj->properties, as this
317 * would be unexpected. */
318 if (obj->properties) {
319 if (UNEXPECTED(GC_REFCOUNT(obj->properties) > 1)) {
321 GC_DELREF(obj->properties);
322 }
324 }
325 zend_hash_reverse_apply(obj->properties, zlo_hash_remove_dyn_props_func);
326 }
327
328 /* unset() declared properties */
329 for (int i = 0; i < reflection_ce->default_properties_count; i++) {
331 if (EXPECTED(prop_info)) {
333 if (Z_TYPE_P(p) != IS_UNDEF) {
335 /* TODO: test final property */
336 && ((obj->ce->ce_flags & ZEND_ACC_FINAL) || (prop_info->flags & ZEND_ACC_FINAL))) {
337 continue;
338 }
340 ZVAL_UNDEF(p);
341 }
343 lazy_properties_count++;
344 }
345 }
346 }
347
348 /* Objects become non-lazy if all properties are made non-lazy before
349 * initialization is triggered. If the object has no properties to begin
350 * with, this happens immediately. */
351 if (UNEXPECTED(!lazy_properties_count)) {
352 return obj;
353 }
354
356
359 } else {
361 }
362
363 zend_lazy_object_info *info = emalloc(sizeof(*info));
364 zend_fcc_dup(&info->u.initializer.fcc, initializer_fcc);
365 ZVAL_COPY(&info->u.initializer.zv, initializer_zv);
366 info->flags = flags;
367 info->lazy_properties_count = lazy_properties_count;
368 zend_lazy_object_set_info(obj, info);
369
370 return obj;
371}
372
376
377/* Mark object as initialized. Lazy properties are initialized to their default
378 * value and the initializer is not called. */
380{
381 ZEND_ASSERT(zend_object_is_lazy(obj));
382 ZEND_ASSERT(!zend_lazy_object_initialized(obj));
383
384 zend_class_entry *ce = obj->ce;
385
387
388 zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce);
389 zval *properties_table = obj->properties_table;
390
392
393 for (int i = 0; i < ce->default_properties_count; i++) {
394 if (Z_PROP_FLAG_P(&properties_table[i]) & IS_PROP_LAZY) {
395 ZVAL_COPY_PROP(&properties_table[i], &default_properties_table[i]);
396 }
397 }
398
400
401 return obj;
402}
403
404/* Revert initializer effects */
405static void zend_lazy_object_revert_init(zend_object *obj, zval *properties_table_snapshot, HashTable *properties_snapshot)
406{
407 zend_class_entry *ce = obj->ce;
408
409 if (ce->default_properties_count) {
410 ZEND_ASSERT(properties_table_snapshot);
411 zval *properties_table = obj->properties_table;
412
413 for (int i = 0; i < ce->default_properties_count; i++) {
415 if (!prop_info) {
416 continue;
417 }
418
419 zval *p = &properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
421 ZVAL_COPY_VALUE_PROP(p, &properties_table_snapshot[OBJ_PROP_TO_NUM(prop_info->offset)]);
422
423 if (Z_ISREF_P(p) && ZEND_TYPE_IS_SET(prop_info->type)) {
425 }
426 }
427
428 efree(properties_table_snapshot);
429 }
430 if (properties_snapshot) {
431 if (obj->properties != properties_snapshot) {
432 ZEND_ASSERT((GC_FLAGS(properties_snapshot) & IS_ARRAY_IMMUTABLE) || GC_REFCOUNT(properties_snapshot) >= 1);
434 obj->properties = properties_snapshot;
435 } else {
436 ZEND_ASSERT((GC_FLAGS(properties_snapshot) & IS_ARRAY_IMMUTABLE) || GC_REFCOUNT(properties_snapshot) > 1);
437 zend_release_properties(properties_snapshot);
438 }
439 } else if (obj->properties) {
441 obj->properties = NULL;
442 }
443
445}
446
447static bool zend_lazy_object_compatible(zend_object *real_object, zend_object *lazy_object)
448{
449 if (EXPECTED(real_object->ce == lazy_object->ce)) {
450 return true;
451 }
452
453 if (!instanceof_function(lazy_object->ce, real_object->ce)) {
454 return false;
455 }
456
457 /* zend_hash_num_elements(ce.properties_info) reports the actual number of
458 * properties. ce.default_properties_count is off by the number of property
459 * overrides. */
460 if (zend_hash_num_elements(&lazy_object->ce->properties_info) != zend_hash_num_elements(&real_object->ce->properties_info)) {
461 return false;
462 }
463
464 return lazy_object->ce->destructor == real_object->ce->destructor
465 && lazy_object->ce->clone == real_object->ce->clone;
466}
467
468/* Initialize a lazy proxy object */
469static zend_object *zend_lazy_object_init_proxy(zend_object *obj)
470{
471 ZEND_ASSERT(zend_object_is_lazy_proxy(obj));
472 ZEND_ASSERT(!zend_lazy_object_initialized(obj));
473
474 /* Prevent object from being released during initialization */
475 GC_ADDREF(obj);
476
477 zend_lazy_object_info *info = zend_lazy_object_get_info(obj);
478
479 /* prevent reentrant initialization */
481
482 /* Call factory */
483 zval retval;
484 int argc = 1;
485 zval zobj;
486 HashTable *named_params = NULL;
487 zend_fcall_info_cache *initializer = &info->u.initializer.fcc;
488 zend_object *instance = NULL;
489
490 ZVAL_OBJ(&zobj, obj);
491
492 zend_call_known_fcc(initializer, &retval, argc, &zobj, named_params);
493
494 if (UNEXPECTED(EG(exception))) {
496 goto exit;
497 }
498
501 zend_type_error("Lazy proxy factory must return an instance of a class compatible with %s, %s returned",
502 ZSTR_VAL(obj->ce->name),
505 goto exit;
506 }
507
508 if (UNEXPECTED(Z_TYPE(retval) != IS_OBJECT || !zend_lazy_object_compatible(Z_OBJ(retval), obj))) {
510 zend_type_error("The real instance class %s is not compatible with the proxy class %s. The proxy must be a instance of the same class as the real instance, or a sub-class with no additional properties, and no overrides of the __destructor or __clone methods.",
512 ZSTR_VAL(obj->ce->name));
514 goto exit;
515 }
516
517 if (UNEXPECTED(Z_OBJ(retval) == obj || zend_object_is_lazy(Z_OBJ(retval)))) {
519 zend_throw_error(NULL, "Lazy proxy factory must return a non-lazy object");
521 goto exit;
522 }
523
524 zend_fcc_dtor(&info->u.initializer.fcc);
526 info->u.instance = Z_OBJ(retval);
529
530 /* unset() properties of the proxy. This ensures that all accesses are be
531 * delegated to the backing instance from now on. */
533 obj->properties = NULL;
534
535 for (int i = 0; i < Z_OBJ(retval)->ce->default_properties_count; i++) {
536 zend_property_info *prop_info = Z_OBJ(retval)->ce->properties_info_table[i];
537 if (EXPECTED(prop_info)) {
538 zval *prop = &obj->properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
539 zend_object_dtor_property(obj, prop);
540 ZVAL_UNDEF(prop);
542 }
543 }
544
545 instance = Z_OBJ(retval);
546
547exit:
548 if (UNEXPECTED(GC_DELREF(obj) == 0)) {
549 zend_throw_error(NULL, "Lazy object was released during initialization");
551 instance = NULL;
552 } else {
553 gc_check_possible_root((zend_refcounted*) obj);
554 }
555
556 return instance;
557}
558
559/* Initialize a lazy object. */
561{
562 ZEND_ASSERT(zend_object_is_lazy(obj));
563
564 /* If obj is an initialized lazy proxy, return the real instance. This
565 * supports the following pattern:
566 * if (zend_lazy_object_must_init(obj)) {
567 * instance = zend_lazy_object_init(obj);
568 * }
569 */
570 if (zend_lazy_object_initialized(obj)) {
571 ZEND_ASSERT(zend_object_is_lazy_proxy(obj));
572 zend_lazy_object_info *info = zend_lazy_object_get_info(obj);
574 if (zend_object_is_lazy(info->u.instance)) {
575 return zend_lazy_object_init(info->u.instance);
576 }
577 return info->u.instance;
578 }
579
580 zend_class_entry *ce = obj->ce;
581
583
584 if (zend_object_is_lazy_proxy(obj)) {
585 return zend_lazy_object_init_proxy(obj);
586 }
587
588 /* Prevent object from being released during initialization */
589 GC_ADDREF(obj);
590
591 zend_fcall_info_cache *initializer = zend_lazy_object_get_initializer_fcc(obj);
592
593 /* Prevent reentrant initialization */
595
596 /* Snapshot dynamic properties */
597 HashTable *properties_snapshot = obj->properties;
598 if (properties_snapshot) {
599 GC_TRY_ADDREF(properties_snapshot);
600 }
601
602 zval *properties_table_snapshot = NULL;
603
604 /* Snapshot declared properties and initialize lazy properties to their
605 * default value */
606 if (ce->default_properties_count) {
607 zval *default_properties_table = CE_DEFAULT_PROPERTIES_TABLE(ce);
608 zval *properties_table = obj->properties_table;
609 properties_table_snapshot = emalloc(sizeof(*properties_table_snapshot) * ce->default_properties_count);
610
611 for (int i = 0; i < ce->default_properties_count; i++) {
612 ZVAL_COPY_PROP(&properties_table_snapshot[i], &properties_table[i]);
613 if (Z_PROP_FLAG_P(&properties_table[i]) & IS_PROP_LAZY) {
614 ZVAL_COPY_PROP(&properties_table[i], &default_properties_table[i]);
615 }
616 }
617 }
618
619 /* Call initializer */
620 zval retval;
621 int argc = 1;
622 zval zobj;
623 HashTable *named_params = NULL;
624 zend_object *instance = NULL;
625
626 ZVAL_OBJ(&zobj, obj);
627
628 zend_call_known_fcc(initializer, &retval, argc, &zobj, named_params);
629
630 if (EG(exception)) {
631 zend_lazy_object_revert_init(obj, properties_table_snapshot, properties_snapshot);
632 goto exit;
633 }
634
635 if (Z_TYPE(retval) != IS_NULL) {
636 zend_lazy_object_revert_init(obj, properties_table_snapshot, properties_snapshot);
638 zend_type_error("Lazy object initializer must return NULL or no value");
639 goto exit;
640 }
641
642 if (properties_table_snapshot) {
643 for (int i = 0; i < obj->ce->default_properties_count; i++) {
644 zval *p = &properties_table_snapshot[i];
645 /* Use zval_ptr_dtor directly here (not zend_object_dtor_property),
646 * as any reference type_source will have already been deleted in
647 * case the prop is not bound to this value anymore. */
648 i_zval_ptr_dtor(p);
649 }
650 efree(properties_table_snapshot);
651 }
652
653 if (properties_snapshot) {
654 zend_release_properties(properties_snapshot);
655 }
656
657 /* Must be very last in this function, for the
658 * zend_lazy_object_has_stale_info() check */
660
661 instance = obj;
662
663exit:
664 if (UNEXPECTED(GC_DELREF(obj) == 0)) {
665 zend_throw_error(NULL, "Lazy object was released during initialization");
667 instance = NULL;
668 } else {
669 gc_check_possible_root((zend_refcounted*) obj);
670 }
671
672 return instance;
673}
674
675/* Mark an object as non-lazy (after all properties were initialized) */
677{
678 ZEND_ASSERT(zend_object_is_lazy(obj));
679 ZEND_ASSERT(!zend_lazy_object_initialized(obj));
680
682
683#if ZEND_DEBUG
684 for (int i = 0; i < obj->ce->default_properties_count; i++) {
686 }
687#endif
688
690}
691
693{
694 ZEND_ASSERT(zend_object_is_lazy(object));
695
696 zend_object *tmp = zend_lazy_object_init(object);
697 if (UNEXPECTED(!tmp)) {
698 if (object->properties) {
699 return object->properties;
700 }
701 return object->properties = zend_new_array(0);
702 }
703
704 object = tmp;
705 ZEND_ASSERT(!zend_lazy_object_must_init(object));
706
707 return zend_std_get_properties_ex(object);
708}
709
710/* Initialize object and clone it. For proxies, we clone both the proxy and its
711 * real instance, and we don't call __clone() on the proxy. */
713{
714 ZEND_ASSERT(zend_object_is_lazy(old_obj));
715
716 if (UNEXPECTED(!zend_lazy_object_initialized(old_obj) && !zend_lazy_object_init(old_obj))) {
718 /* Clone handler must always return an object. It is discarded later due
719 * to the exception. */
720 zval zv;
721 object_init_ex(&zv, old_obj->ce);
723 return Z_OBJ(zv);
724 }
725
726 if (!zend_object_is_lazy_proxy(old_obj)) {
727 return zend_objects_clone_obj(old_obj);
728 }
729
730 zend_lazy_object_info *info = zend_lazy_object_get_info(old_obj);
731 zend_class_entry *ce = old_obj->ce;
732 zend_object *new_proxy = zend_objects_new(ce);
733
734 /* Iterate in reverse to avoid overriding Z_PROP_FLAG_P() of child props with added hooks (GH-17870). */
735 for (int i = ce->default_properties_count - 1; i >= 0; i--) {
736 zval *p = &new_proxy->properties_table[i];
737 ZVAL_UNDEF(p);
738 Z_PROP_FLAG_P(p) = 0;
739
741 if (prop_info) {
742 zval *p = &new_proxy->properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
744 }
745 }
746
747 OBJ_EXTRA_FLAGS(new_proxy) = OBJ_EXTRA_FLAGS(old_obj);
748
749 zend_lazy_object_info *new_info = emalloc(sizeof(*info));
750 *new_info = *info;
751 new_info->u.instance = zend_objects_clone_obj(info->u.instance);
752
753 zend_lazy_object_set_info(new_proxy, new_info);
754
755 return new_proxy;
756}
757
759{
760 ZEND_ASSERT(zend_object_is_lazy(object));
761
762 if (zend_object_is_lazy_proxy(object)) {
763 if (zend_lazy_object_initialized(object)) {
764 HashTable *properties = zend_new_array(0);
765 zval instance;
766 ZVAL_OBJ(&instance, zend_lazy_object_get_instance(object));
767 Z_ADDREF(instance);
768 zend_hash_str_add(properties, "instance", strlen("instance"), &instance);
769 *is_temp = 1;
770 return properties;
771 }
772 }
773
774 *is_temp = 0;
776}
777
779{
780 ZEND_ASSERT(zend_object_is_lazy(zobj));
781
782 zend_lazy_object_info *info = zend_lazy_object_get_info(zobj);
784
785 if (zend_lazy_object_initialized(zobj)) {
786 ZEND_ASSERT(zend_object_is_lazy_proxy(zobj));
787 zend_get_gc_buffer_add_obj(gc_buffer, info->u.instance);
788 zend_get_gc_buffer_use(gc_buffer, table, n);
789 /* Initialized proxy object can not have properties */
790 return NULL;
791 }
792
794 if (fcc->object) {
795 zend_get_gc_buffer_add_obj(gc_buffer, fcc->object);
796 }
797 if (fcc->closure) {
798 zend_get_gc_buffer_add_obj(gc_buffer, fcc->closure);
799 }
800 zend_get_gc_buffer_add_zval(gc_buffer, &info->u.initializer.zv);
801
802 /* Uninitialized lazy objects can not have dynamic properties, so we can
803 * ignore zobj->properties. */
804 zval *prop = zobj->properties_table;
805 zval *end = prop + zobj->ce->default_properties_count;
806 for ( ; prop < end; prop++) {
807 zend_get_gc_buffer_add_zval(gc_buffer, prop);
808 }
809
810 zend_get_gc_buffer_use(gc_buffer, table, n);
811 return NULL;
812}
813
815{
816 ZEND_ASSERT(zend_object_is_lazy_proxy(obj));
817
819 intptr_t prop_num = slot - obj->properties_table;
820 if (prop_num >= 0 && prop_num < obj->ce->default_properties_count) {
821 if (table[prop_num]) {
822 return table[prop_num];
823 } else {
824 return zend_get_property_info_for_slot_slow(obj, slot);
825 }
826 }
827
828 if (!zend_lazy_object_initialized(obj)) {
829 return NULL;
830 }
831
833 return zend_get_property_info_for_slot(obj, slot);
834}
bool exception
Definition assert.c:30
uint32_t u
Definition cdf.c:78
zval * zv
Definition ffi.c:3975
zend_long n
Definition ffi.c:4979
zend_string * res
Definition ffi.c:4692
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
unsigned const char * end
Definition php_ffi.h:51
#define zend_hash_str_add(...)
Definition phpdbg.h:77
p
Definition session.c:1105
HashTable properties_info
Definition zend.h:164
zend_string * name
Definition zend.h:149
uint32_t ce_flags
Definition zend.h:156
int default_properties_count
Definition zend.h:158
char type
Definition zend.h:148
struct _zend_property_info ** properties_info_table
Definition zend.h:170
zend_class_entry * parent
Definition zend.h:152
zend_function * clone
Definition zend.h:174
zend_function * destructor
Definition zend.h:173
zend_object * closure
Definition zend_API.h:64
zend_object * object
Definition zend_API.h:63
zend_fcall_info_cache fcc
zend_lazy_object_flags_t flags
struct _zend_lazy_object_info::@072225263375046243115374153365053243337217100056::@150272324151245360342176347254272073155373217166 initializer
union _zend_lazy_object_info::@072225263375046243115374153365053243337217100056 u
zend_object_dtor_obj_t dtor_obj
zend_class_entry * ce
Definition zend_types.h:560
zval properties_table[1]
Definition zend_types.h:563
const zend_object_handlers * handlers
Definition zend_types.h:561
uint32_t handle
Definition zend_types.h:558
HashTable * properties
Definition zend_types.h:562
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API zend_class_entry * zend_standard_class_def
Definition zend.c:83
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type)
Definition zend_API.c:1518
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type)
Definition zend_API.c:1849
struct _zend_fcall_info_cache zend_fcall_info_cache
#define CE_DEFAULT_PROPERTIES_TABLE(ce)
Definition zend_API.h:334
#define efree(ptr)
Definition zend_alloc.h:155
#define emalloc(size)
Definition zend_alloc.h:151
struct _zval_struct zval
strlen(string $string)
exit(string|int $status=0)
#define OBJ_PROP_TO_NUM(offset)
#define ZEND_ACC_FINAL
#define ZEND_ACC_UNINSTANTIABLE
#define ZEND_ACC_READONLY
struct _zend_property_info zend_property_info
#define ZEND_ACC_CONSTANTS_UPDATED
#define ZEND_INTERNAL_CLASS
#define ZEND_API
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define ZEND_REF_ADD_TYPE_SOURCE(ref, source)
ZEND_API zend_get_gc_buffer * zend_get_gc_buffer_create(void)
Definition zend_gc.c:2130
#define CG(v)
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_destroy(HashTable *ht)
Definition zend_hash.c:1727
ZEND_API void ZEND_FASTCALL zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func)
Definition zend_hash.c:2192
ZEND_API zend_result ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h)
Definition zend_hash.c:1692
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent)
Definition zend_hash.h:108
#define ZEND_HASH_APPLY_STOP
Definition zend_hash.h:148
#define ZEND_HASH_APPLY_REMOVE
Definition zend_hash.h:147
#define HT_ITERATORS_COUNT(ht)
Definition zend_hash.h:74
#define zend_new_array(size)
Definition zend_hash.h:338
HashTable * zend_lazy_object_debug_info(zend_object *object, int *is_temp)
ZEND_API bool zend_class_can_be_lazy(zend_class_entry *ce)
ZEND_API zend_object * zend_lazy_object_mark_as_initialized(zend_object *obj)
zend_object * zend_lazy_object_get_instance(zend_object *obj)
HashTable * zend_lazy_object_get_gc(zend_object *zobj, zval **table, int *n)
zend_lazy_object_flags_t zend_lazy_object_get_flags(zend_object *obj)
ZEND_API zend_object * zend_lazy_object_init(zend_object *obj)
struct _zend_lazy_object_info zend_lazy_object_info
ZEND_API zend_object * zend_object_make_lazy(zend_object *obj, zend_class_entry *reflection_ce, zval *initializer_zv, zend_fcall_info_cache *initializer_fcc, zend_lazy_object_flags_t flags)
zend_property_info * zend_lazy_object_get_property_info_for_slot(zend_object *obj, zval *slot)
void zend_lazy_object_realize(zend_object *obj)
ZEND_API HashTable * zend_lazy_object_get_properties(zend_object *object)
bool zend_lazy_object_decr_lazy_props(zend_object *obj)
void zend_lazy_objects_init(zend_lazy_objects_store *store)
zval * zend_lazy_object_get_initializer_zv(zend_object *obj)
zend_object * zend_lazy_object_clone(zend_object *old_obj)
void zend_lazy_object_del_info(zend_object *obj)
void zend_lazy_objects_destroy(zend_lazy_objects_store *store)
uint8_t zend_lazy_object_flags_t
#define ZEND_LAZY_OBJECT_STRATEGY_MASK
#define ZEND_LAZY_OBJECT_STRATEGY_GHOST
#define ZEND_LAZY_OBJECT_USER_MASK
struct _zend_lazy_objects_store zend_lazy_objects_store
#define ZEND_LAZY_OBJECT_SKIP_DESTRUCTOR
#define ZEND_LAZY_OBJECT_INITIALIZED
#define ZEND_LAZY_OBJECT_STRATEGY_PROXY
ZEND_API HashTable * zend_get_properties_no_lazy_init(zend_object *zobj)
#define zend_release_properties(ht)
ZEND_API zend_object *ZEND_FASTCALL zend_objects_new(zend_class_entry *ce)
ZEND_API void zend_objects_destroy_object(zend_object *object)
void zend_object_dtor_property(zend_object *object, zval *p)
ZEND_API zend_object * zend_objects_clone_obj(zend_object *old_object)
void zend_object_dtor_dynamic_properties(zend_object *object)
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object)
ZEND_API ZEND_COLD zend_property_info * zend_get_property_info_for_slot_slow(zend_object *obj, zval *slot)
#define EXPECTED(condition)
#define ZEND_ASSERT(c)
#define UNEXPECTED(condition)
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define Z_ISREF_P(zval_p)
Definition zend_types.h:954
#define ZVAL_UNDEF(z)
#define IS_UNDEF
Definition zend_types.h:600
#define IS_OBJ_LAZY_PROXY
Definition zend_types.h:836
#define ZVAL_COPY_VALUE_PROP(z, v)
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_PROP_REINITABLE
#define Z_PTR_P(zval_p)
#define OBJ_EXTRA_FLAGS(obj)
Definition zend_types.h:838
#define GC_DELREF(p)
Definition zend_types.h:710
#define GC_FLAGS(p)
Definition zend_types.h:756
#define GC_ADDREF(p)
Definition zend_types.h:709
#define GC_TRY_ADDREF(p)
Definition zend_types.h:713
#define IS_OBJ_DESTRUCTOR_CALLED
Definition zend_types.h:828
#define IS_NULL
Definition zend_types.h:601
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define Z_ADDREF(z)
#define ZEND_TYPE_IS_SET(t)
Definition zend_types.h:166
#define ZVAL_COPY(z, v)
struct _zend_refcounted zend_refcounted
Definition zend_types.h:95
#define Z_REF_P(zval_p)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define IS_PROP_UNINIT
#define IS_ARRAY_IMMUTABLE
Definition zend_types.h:823
#define ZVAL_COPY_PROP(z, v)
#define IS_PROP_LAZY
#define IS_OBJ_LAZY_UNINITIALIZED
Definition zend_types.h:835
#define Z_PROP_FLAG_P(z)
#define GC_REFCOUNT(p)
Definition zend_types.h:707
#define Z_TYPE(zval)
Definition zend_types.h:659
#define IS_INDIRECT
Definition zend_types.h:623
#define GC_DEL_FLAGS(p, flags)
Definition zend_types.h:762
#define OBJ_FLAGS(obj)
Definition zend_types.h:831
#define GC_ADD_FLAGS(p, flags)
Definition zend_types.h:759
#define Z_OBJ(zval)
Definition zend_types.h:989
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
zval retval
zend_property_info * prop_info
bool result
object
zend_object * zobj