Skip to content

Commit d222bd6

Browse files
committed
Build properties_info_table during compilation
And cache it in opcache.
1 parent 5371206 commit d222bd6

11 files changed

+102
-49
lines changed

Zend/zend_API.c

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

27442744
if (parent_ce) {
27452745
zend_do_inheritance(register_class, parent_ce);
2746+
zend_build_properties_info_table(register_class);
27462747
}
27472748
return register_class;
27482749
}
@@ -3715,10 +3716,20 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
37153716
property_info->offset = property_info_ptr->offset;
37163717
zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
37173718
zend_hash_del(&ce->properties_info, name);
3719+
3720+
ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
3721+
ZEND_ASSERT(ce->properties_info_table != NULL);
3722+
ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
37183723
} else {
37193724
property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
37203725
ce->default_properties_count++;
37213726
ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
3727+
3728+
/* For user classes this is handled during linking */
3729+
if (ce->type == ZEND_INTERNAL_CLASS) {
3730+
ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
3731+
ce->properties_info_table[ce->default_properties_count - 1] = property_info;
3732+
}
37223733
}
37233734
ZVAL_COPY_VALUE(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)], property);
37243735
}

Zend/zend_compile.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6332,6 +6332,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
63326332
CG(zend_lineno) = decl->end_lineno;
63336333
ce->ce_flags |= ZEND_ACC_LINKED;
63346334
zend_do_inheritance(ce, parent_ce);
6335+
zend_build_properties_info_table(ce);
63356336
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) {
63366337
zend_verify_abstract_class(ce);
63376338
}
@@ -6343,6 +6344,7 @@ void zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
63436344
} else {
63446345
if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
63456346
zend_string_release(lcname);
6347+
zend_build_properties_info_table(ce);
63466348
ce->ce_flags |= ZEND_ACC_LINKED;
63476349
return;
63486350
}

Zend/zend_inheritance.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,42 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa
782782
}
783783
/* }}} */
784784

785+
void zend_build_properties_info_table(zend_class_entry *ce)
786+
{
787+
zend_property_info **table, *prop;
788+
if (ce->default_properties_count == 0) {
789+
return;
790+
}
791+
792+
ZEND_ASSERT(ce->properties_info_table == NULL);
793+
if (ce->type == ZEND_USER_CLASS) {
794+
ce->properties_info_table = table = zend_arena_alloc(&CG(arena),
795+
sizeof(zend_property_info *) * ce->default_properties_count);
796+
} else {
797+
ce->properties_info_table = table = pemalloc(
798+
sizeof(zend_property_info *) * ce->default_properties_count, 1);
799+
}
800+
801+
if (ce->parent && ce->parent->default_properties_count != 0) {
802+
zend_property_info **parent_table = ce->parent->properties_info_table;
803+
memcpy(
804+
table, parent_table,
805+
sizeof(zend_property_info *) * ce->parent->default_properties_count
806+
);
807+
808+
/* Child did not add any new properties, we are done */
809+
if (ce->default_properties_count == ce->parent->default_properties_count) {
810+
return;
811+
}
812+
}
813+
814+
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
815+
if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) {
816+
table[OBJ_PROP_TO_NUM(prop->offset)] = prop;
817+
}
818+
} ZEND_HASH_FOREACH_END();
819+
}
820+
785821
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
786822
{
787823
zend_property_info *property_info;
@@ -1936,6 +1972,8 @@ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent)
19361972
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) {
19371973
zend_verify_abstract_class(ce);
19381974
}
1975+
1976+
zend_build_properties_info_table(ce);
19391977
}
19401978
/* }}} */
19411979

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
END_EXTERN_C()
3637

Zend/zend_object_handlers.c

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -58,39 +58,6 @@
5858
called, we cal __call handler.
5959
*/
6060

61-
ZEND_API zend_property_info **zend_build_properties_info_table(zend_class_entry *ce)
62-
{
63-
zend_property_info *prop;
64-
zend_property_info **table = pemalloc(
65-
sizeof(zend_property_info *) * ce->default_properties_count,
66-
ce->type == ZEND_INTERNAL_CLASS
67-
);
68-
69-
ZEND_ASSERT(ce->properties_info_table == NULL);
70-
ZEND_ASSERT(ce->default_properties_count != 0);
71-
ce->properties_info_table = table;
72-
73-
if (ce->parent && ce->parent->default_properties_count != 0) {
74-
zend_property_info **parent_table = zend_get_properties_info_table(ce->parent);
75-
memcpy(
76-
table, parent_table,
77-
sizeof(zend_property_info *) * ce->parent->default_properties_count
78-
);
79-
80-
/* Child did not add any new properties, we are done */
81-
if (ce->default_properties_count == ce->parent->default_properties_count) {
82-
return table;
83-
}
84-
}
85-
86-
ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
87-
if (prop->ce == ce && (prop->flags & ZEND_ACC_STATIC) == 0) {
88-
table[OBJ_PROP_TO_NUM(prop->offset)] = prop;
89-
}
90-
} ZEND_HASH_FOREACH_END();
91-
return table;
92-
}
93-
9461
ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
9562
{
9663
if (!zobj->properties) {

Zend/zend_object_handlers.h

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -242,22 +242,11 @@ ZEND_API HashTable *zend_get_properties_for(zval *obj, zend_prop_purpose purpose
242242
} \
243243
} while (0)
244244

245-
ZEND_API struct _zend_property_info **zend_build_properties_info_table(zend_class_entry *ce);
246245
ZEND_API int zend_check_property_info_access(struct _zend_property_info *prop_info);
247246

248-
static inline struct _zend_property_info **zend_get_properties_info_table(zend_class_entry *ce)
249-
{
250-
ZEND_ASSERT(ce->default_properties_count != 0);
251-
if (ce->properties_info_table) {
252-
return ce->properties_info_table;
253-
}
254-
255-
return zend_build_properties_info_table(ce);
256-
}
257-
258247
static inline struct _zend_property_info *zend_get_property_info_for_slot(zend_object *obj, zval *slot)
259248
{
260-
struct _zend_property_info **table = zend_get_properties_info_table(obj->ce);
249+
struct _zend_property_info **table = obj->ce->properties_info_table;
261250
intptr_t prop_num = slot - obj->properties_table;
262251
ZEND_ASSERT(prop_num >= 0 && prop_num < obj->ce->default_properties_count);
263252
return table[prop_num];

Zend/zend_opcode.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,6 @@ ZEND_API void destroy_zend_class(zval *zv)
284284
_destroy_zend_class_traits_info(ce);
285285
}
286286

287-
if (ce->properties_info_table) {
288-
efree(ce->properties_info_table);
289-
}
290-
291287
break;
292288
case ZEND_INTERNAL_CLASS:
293289
if (ce->default_properties_table) {

ext/opcache/zend_accelerator_util_funcs.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,16 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
279279
/* constants table */
280280
zend_hash_clone_constants(&ce->constants_table, &old_ce->constants_table);
281281

282+
if (ce->properties_info_table) {
283+
int i;
284+
ce->properties_info_table = ARENA_REALLOC(ce->properties_info_table);
285+
for (i = 0; i < ce->default_properties_count; i++) {
286+
if (IN_ARENA(ce->properties_info_table[i])) {
287+
ce->properties_info_table[i] = ARENA_REALLOC(ce->properties_info_table[i]);
288+
}
289+
}
290+
}
291+
282292
if (ce->num_interfaces) {
283293
zend_class_name *interface_names;
284294

ext/opcache/zend_file_cache.c

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

656+
if (ce->properties_info_table) {
657+
uint32_t i;
658+
zend_property_info **table;
659+
660+
SERIALIZE_PTR(ce->properties_info_table);
661+
table = ce->properties_info_table;
662+
UNSERIALIZE_PTR(table);
663+
664+
for (i = 0; i < ce->default_properties_count; i++) {
665+
SERIALIZE_PTR(table[i]);
666+
}
667+
}
668+
656669
if (ce->num_interfaces) {
657670
uint32_t i;
658671
zend_class_name *interface_names;
@@ -1294,6 +1307,15 @@ static void zend_file_cache_unserialize_class(zval *zv,
12941307
zend_file_cache_unserialize_hash(&ce->properties_info,
12951308
script, buf, zend_file_cache_unserialize_prop_info, NULL);
12961309

1310+
if (ce->properties_info_table) {
1311+
uint32_t i;
1312+
UNSERIALIZE_PTR(ce->properties_info_table);
1313+
1314+
for (i = 0; i < ce->default_properties_count; i++) {
1315+
UNSERIALIZE_PTR(ce->properties_info_table[i]);
1316+
}
1317+
}
1318+
12971319
if (ce->num_interfaces) {
12981320
uint32_t i;
12991321

ext/opcache/zend_persist.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,19 @@ static void zend_persist_class_entry(zval *zv)
778778
zend_hash_persist(&ce->properties_info, zend_persist_property_info);
779779
HT_FLAGS(&ce->properties_info) &= (HASH_FLAG_INITIALIZED | HASH_FLAG_STATIC_KEYS);
780780

781+
if (ce->properties_info_table) {
782+
int i;
783+
784+
size_t size = sizeof(zend_property_info *) * ce->default_properties_count;
785+
memcpy(ZCG(arena_mem), ce->properties_info_table, size);
786+
ce->properties_info_table = ZCG(arena_mem);
787+
ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(size));
788+
789+
for (i = 0; i < ce->default_properties_count; i++) {
790+
ce->properties_info_table[i] = zend_shared_alloc_get_xlat_entry(ce->properties_info_table[i]);
791+
}
792+
}
793+
781794
if (ce->num_interfaces) {
782795
uint32_t i = 0;
783796

ext/opcache/zend_persist_calc.c

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

344344
zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc);
345345

346+
if (ce->properties_info_table) {
347+
ADD_ARENA_SIZE(sizeof(zend_property_info *) * ce->default_properties_count);
348+
}
349+
346350
if (ce->num_interfaces) {
347351
uint32_t i;
348352

0 commit comments

Comments
 (0)