Skip to content

Commit c89b5ba

Browse files
committed
Add slot to prop info mapping mechanism
Taken from PR php#3573, minus the foreach/iteration parts.
1 parent 9788344 commit c89b5ba

11 files changed

+115
-0
lines changed

Zend/zend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ struct _zend_class_entry {
133133
HashTable properties_info;
134134
HashTable constants_table;
135135

136+
struct _zend_property_info **properties_info_table;
137+
136138
zend_function *constructor;
137139
zend_function *destructor;
138140
zend_function *clone;

Zend/zend_API.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2658,6 +2658,7 @@ ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *cla
26582658

26592659
if (parent_ce) {
26602660
zend_do_inheritance(register_class, parent_ce);
2661+
zend_build_properties_info_table(register_class);
26612662
}
26622663
return register_class;
26632664
}
@@ -3632,10 +3633,20 @@ ZEND_API int zend_declare_typed_property(zend_class_entry *ce, zend_string *name
36323633
property_info->offset = property_info_ptr->offset;
36333634
zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
36343635
zend_hash_del(&ce->properties_info, name);
3636+
3637+
ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
3638+
ZEND_ASSERT(ce->properties_info_table != NULL);
3639+
ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
36353640
} else {
36363641
property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
36373642
ce->default_properties_count++;
36383643
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
3644+
3645+
/* For user classes this is handled during linking */
3646+
if (ce->type == ZEND_INTERNAL_CLASS) {
3647+
ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
3648+
ce->properties_info_table[ce->default_properties_count - 1] = property_info;
3649+
}
36393650
}
36403651
ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property);
36413652
}

Zend/zend_compile.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
16131613

16141614
ce->default_properties_count = 0;
16151615
ce->default_static_members_count = 0;
1616+
ce->properties_info_table = NULL;
16161617

16171618
if (nullify_handlers) {
16181619
ce->constructor = NULL;
@@ -6495,6 +6496,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
64956496
CG(zend_lineno) = decl->end_lineno;
64966497
ce->ce_flags |= ZEND_ACC_LINKED;
64976498
zend_do_inheritance(ce, parent_ce);
6499+
zend_build_properties_info_table(ce);
64986500
if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
64996501
zend_verify_abstract_class(ce);
65006502
}
@@ -6506,6 +6508,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
65066508
} else {
65076509
if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
65086510
zend_string_release(lcname);
6511+
zend_build_properties_info_table(ce);
65096512
ce->ce_flags |= ZEND_ACC_LINKED;
65106513
return;
65116514
}

Zend/zend_inheritance.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,42 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa
846846
}
847847
/* }}} */
848848

849+
void zend_build_properties_info_table(zend_class_entry *ce)
850+
{
851+
zend_property_info **table, *prop;
852+
if (ce->default_properties_count == 0) {
853+
return;
854+
}
855+
856+
ZEND_ASSERT(ce->properties_info_table == NULL);
857+
if (ce->type == ZEND_USER_CLASS) {
858+
ce->properties_info_table = table = zend_arena_alloc(&CG(arena),
859+
sizeof(zend_property_info *) * ce->default_properties_count);
860+
} else {
861+
ce->properties_info_table = table = pemalloc(
862+
sizeof(zend_property_info *) * ce->default_properties_count, 1);
863+
}
864+
865+
if (ce->parent && ce->parent->default_properties_count != 0) {
866+
zend_property_info **parent_table = ce->parent->properties_info_table;
867+
memcpy(
868+
table, parent_table,
869+
sizeof(zend_property_info *) * ce->parent->default_properties_count
870+
);
871+
872+
/* Child did not add any new properties, we are done */
873+
if (ce->default_properties_count == ce->parent->default_properties_count) {
874+
return;
875+
}
876+
}
877+
878+
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
879+
if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) {
880+
table[OBJ_PROP_TO_NUM(prop->offset)] = prop;
881+
}
882+
} ZEND_HASH_FOREACH_END();
883+
}
884+
849885
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
850886
{
851887
zend_property_info *property_info;
@@ -2003,6 +2039,8 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent)
20032039
if ((ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) == ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
20042040
zend_verify_abstract_class(ce);
20052041
}
2042+
2043+
zend_build_properties_info_table(ce);
20062044
}
20072045
/* }}} */
20082046

Zend/zend_inheritance.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent_
3131

3232
void zend_verify_abstract_class(zend_class_entry *ce);
3333
void zend_check_deprecated_constructor(const zend_class_entry *ce);
34+
void zend_build_properties_info_table(zend_class_entry *ce);
3435

3536
zend_string* zend_resolve_property_type(zend_string *name, zend_class_entry *scope);
3637

Zend/zend_object_handlers.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose
246246
} \
247247
} while (0)
248248

249+
static inline struct _zend_property_info *zend_get_property_info_for_slot(zend_object *obj, zval *slot)
250+
{
251+
struct _zend_property_info **table = obj->ce->properties_info_table;
252+
intptr_t prop_num = slot - obj->properties_table;
253+
ZEND_ASSERT(prop_num >= 0 && prop_num < obj->ce->default_properties_count);
254+
return table[prop_num];
255+
}
256+
249257
#define zend_free_trampoline(func) do { \
250258
if ((func) == &EG(trampoline)) { \
251259
EG(trampoline).common.function_name = NULL; \

Zend/zend_opcode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ ZEND_API void destroy_zend_class(zval *zv)
374374
if (ce->num_interfaces > 0) {
375375
free(ce->interfaces);
376376
}
377+
if (ce->properties_info_table) {
378+
free(ce->properties_info_table);
379+
}
377380
free(ce);
378381
break;
379382
}

ext/opcache/zend_accelerator_util_funcs.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,16 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
312312
/* constants table */
313313
zend_hash_clone_constants(&ce->constants_table);
314314

315+
if (ce->properties_info_table) {
316+
int i;
317+
ce->properties_info_table = ARENA_REALLOC(ce->properties_info_table);
318+
for (i = 0; i < ce->default_properties_count; i++) {
319+
if (IN_ARENA(ce->properties_info_table[i])) {
320+
ce->properties_info_table[i] = ARENA_REALLOC(ce->properties_info_table[i]);
321+
}
322+
}
323+
}
324+
315325
if (ce->num_interfaces) {
316326
zend_class_name *interface_names;
317327

ext/opcache/zend_file_cache.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,19 @@ static void zend_file_cache_serialize_class(zval *zv,
660660
SERIALIZE_STR(ce->info.user.doc_comment);
661661
zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
662662

663+
if (ce->properties_info_table) {
664+
uint32_t i;
665+
zend_property_info **table;
666+
667+
SERIALIZE_PTR(ce->properties_info_table);
668+
table = ce->properties_info_table;
669+
UNSERIALIZE_PTR(table);
670+
671+
for (i = 0; i < ce->default_properties_count; i++) {
672+
SERIALIZE_PTR(table[i]);
673+
}
674+
}
675+
663676
if (ce->num_interfaces) {
664677
uint32_t i;
665678
zend_class_name *interface_names;
@@ -1325,6 +1338,15 @@ static void zend_file_cache_unserialize_class(zval *zv,
13251338
zend_file_cache_unserialize_hash(&ce->properties_info,
13261339
script, buf, zend_file_cache_unserialize_prop_info, NULL);
13271340

1341+
if (ce->properties_info_table) {
1342+
uint32_t i;
1343+
UNSERIALIZE_PTR(ce->properties_info_table);
1344+
1345+
for (i = 0; i < ce->default_properties_count; i++) {
1346+
UNSERIALIZE_PTR(ce->properties_info_table[i]);
1347+
}
1348+
}
1349+
13281350
if (ce->num_interfaces) {
13291351
uint32_t i;
13301352

ext/opcache/zend_persist.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,19 @@ static void zend_persist_class_entry(zval *zv)
872872
zend_hash_persist(&ce->properties_info, zend_persist_property_info);
873873
HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_UNINITIALIZED | HASH_FLAG_STATIC_KEYS);
874874

875+
if (ce->properties_info_table) {
876+
int i;
877+
878+
size_t size = sizeof(zend_property_info *) * ce->default_properties_count;
879+
memcpy(ZCG(arena_mem), ce->properties_info_table, size);
880+
ce->properties_info_table = ZCG(arena_mem);
881+
ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(size));
882+
883+
for (i = 0; i < ce->default_properties_count; i++) {
884+
ce->properties_info_table[i] = zend_shared_alloc_get_xlat_entry(ce->properties_info_table[i]);
885+
}
886+
}
887+
875888
if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_LINKED)) {
876889
uint32_t i = 0;
877890

ext/opcache/zend_persist_calc.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ static void zend_persist_class_entry_calc(zval *zv)
387387

388388
zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc);
389389

390+
if (ce->properties_info_table) {
391+
ADD_ARENA_SIZE(sizeof(zend_property_info *) * ce->default_properties_count);
392+
}
393+
390394
if (ce->num_interfaces) {
391395
uint32_t i;
392396

0 commit comments

Comments
 (0)