Skip to content

Commit cd468a6

Browse files
committed
defer compiling inner classes
1 parent 3848383 commit cd468a6

File tree

1 file changed

+40
-10
lines changed

1 file changed

+40
-10
lines changed

Zend/zend_compile.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9094,10 +9094,9 @@ static void zend_compile_use_trait(zend_ast *ast) /* {{{ */
90949094
}
90959095
/* }}} */
90969096

9097-
static void zend_compile_implements(zend_ast *ast) /* {{{ */
9097+
static void zend_compile_implements(zend_ast *ast, zend_class_entry *ce) /* {{{ */
90989098
{
90999099
zend_ast_list *list = zend_ast_get_list(ast);
9100-
zend_class_entry *ce = CG(active_class_entry);
91019100
zend_class_name *interface_names;
91029101
uint32_t i;
91039102

@@ -9155,6 +9154,17 @@ static void zend_compile_enum_backing_type(zend_class_entry *ce, zend_ast *enum_
91559154
zend_type_release(type, 0);
91569155
}
91579156

9157+
HashTable *inner_class_queue = NULL;
9158+
9159+
static void zend_defer_class_decl(zend_ast *ast) {
9160+
if (inner_class_queue == NULL) {
9161+
ALLOC_HASHTABLE(inner_class_queue);
9162+
zend_hash_init(inner_class_queue, 8, NULL, ZVAL_PTR_DTOR, 0);
9163+
}
9164+
9165+
zend_hash_next_index_insert_ptr(inner_class_queue, ast);
9166+
}
9167+
91589168
static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel) /* {{{ */
91599169
{
91609170
zend_ast_decl *decl = (zend_ast_decl *) ast;
@@ -9285,16 +9295,16 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
92859295
zend_resolve_const_class_name_reference(extends_ast, "class name");
92869296
}
92879297

9298+
if (implements_ast) {
9299+
zend_compile_implements(implements_ast, ce);
9300+
}
9301+
92889302
CG(active_class_entry) = ce;
92899303

92909304
if (decl->child[3]) {
92919305
zend_compile_attributes(&ce->attributes, decl->child[3], 0, ZEND_ATTRIBUTE_TARGET_CLASS, 0);
92929306
}
92939307

9294-
if (implements_ast) {
9295-
zend_compile_implements(implements_ast);
9296-
}
9297-
92989308
if (ce->ce_flags & ZEND_ACC_ENUM) {
92999309
if (enum_backing_type_ast != NULL) {
93009310
zend_compile_enum_backing_type(ce, enum_backing_type_ast);
@@ -9312,8 +9322,6 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
93129322
zend_verify_abstract_class(ce);
93139323
}
93149324

9315-
CG(active_class_entry) = original_ce;
9316-
93179325
if (toplevel) {
93189326
ce->ce_flags |= ZEND_ACC_TOP_LEVEL;
93199327
}
@@ -9334,7 +9342,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
93349342
&& !zend_compile_ignore_class(parent_ce, ce->info.user.filename)) {
93359343
if (zend_try_early_bind(ce, parent_ce, lcname, NULL)) {
93369344
zend_string_release(lcname);
9337-
return;
9345+
goto compile_inner_classes;
93389346
}
93399347
}
93409348
} else if (EXPECTED(zend_hash_add_ptr(CG(class_table), lcname, ce) != NULL)) {
@@ -9343,7 +9351,7 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
93439351
zend_inheritance_check_override(ce);
93449352
ce->ce_flags |= ZEND_ACC_LINKED;
93459353
zend_observer_class_linked_notify(ce, lcname);
9346-
return;
9354+
goto compile_inner_classes;
93479355
} else {
93489356
goto link_unbound;
93499357
}
@@ -9413,6 +9421,24 @@ static void zend_compile_class_decl(znode *result, zend_ast *ast, bool toplevel)
94139421
opline->result.opline_num = -1;
94149422
}
94159423
}
9424+
compile_inner_classes:
9425+
9426+
if (inner_class_queue == NULL) {
9427+
CG(active_class_entry) = original_ce;
9428+
return;
9429+
}
9430+
9431+
HashTable *queue = inner_class_queue;
9432+
inner_class_queue = NULL;
9433+
9434+
ZEND_HASH_FOREACH_PTR(queue, ast) {
9435+
zend_compile_class_decl(NULL, ast, 0);
9436+
} ZEND_HASH_FOREACH_END();
9437+
9438+
CG(active_class_entry) = original_ce;
9439+
9440+
zend_hash_destroy(queue);
9441+
FREE_HASHTABLE(queue);
94169442
}
94179443
/* }}} */
94189444

@@ -11692,6 +11718,10 @@ static void zend_compile_stmt(zend_ast *ast) /* {{{ */
1169211718
zend_compile_use(ast);
1169311719
break;
1169411720
case ZEND_AST_CONST_DECL:
11721+
if (CG(active_class_entry)) {
11722+
zend_defer_class_decl(ast);
11723+
break;
11724+
}
1169511725
zend_compile_const_decl(ast);
1169611726
break;
1169711727
case ZEND_AST_NAMESPACE:

0 commit comments

Comments
 (0)