Skip to content

Commit 89b2d88

Browse files
committed
Register class before fetching parent
We want the class declaration to be available while compiling the parent class.
1 parent 9ecc0a4 commit 89b2d88

24 files changed

+1077
-1261
lines changed

Zend/zend_compile.c

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ ZEND_API int do_bind_function(zval *lcname) /* {{{ */
10431043
}
10441044
/* }}} */
10451045

1046-
ZEND_API int do_bind_class(zval *lcname, zend_class_entry *parent_ce) /* {{{ */
1046+
ZEND_API int do_bind_class(zval *lcname) /* {{{ */
10471047
{
10481048
zend_class_entry *ce;
10491049
zval *rtd_key, *zv;
@@ -1070,7 +1070,7 @@ ZEND_API int do_bind_class(zval *lcname, zend_class_entry *parent_ce) /* {{{ */
10701070
return FAILURE;
10711071
}
10721072

1073-
zend_do_link_class(ce, parent_ce);
1073+
zend_do_link_class(ce);
10741074
return SUCCESS;
10751075
}
10761076
/* }}} */
@@ -1113,7 +1113,7 @@ ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_
11131113
zend_op *end = opline + op_array->last;
11141114

11151115
while (opline < end) {
1116-
if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
1116+
if (opline->opcode == ZEND_DECLARE_CLASS_DELAYED) {
11171117
*prev_opline_num = opline - op_array->opcodes;
11181118
prev_opline_num = &opline->result.opline_num;
11191119
}
@@ -1136,11 +1136,10 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint3
11361136
while (opline_num != (uint32_t)-1) {
11371137
const zend_op *opline = &op_array->opcodes[opline_num];
11381138
zval *lcname = RT_CONSTANT(opline, opline->op1);
1139-
zval *parent_name = RT_CONSTANT(opline, opline->op2);
11401139
zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname + 1));
1141-
zend_class_entry *parent_ce = zend_lookup_class_ex(Z_STR_P(parent_name), Z_STR_P(parent_name + 1), 0);
1140+
zend_class_entry *parent_ce = zend_lookup_class(ce->parent_name);
11421141
if (ce && parent_ce && zend_can_early_bind(ce, parent_ce)) {
1143-
do_bind_class(lcname, parent_ce);
1142+
do_bind_class(lcname);
11441143
}
11451144
opline_num = op_array->opcodes[opline_num].result.opline_num;
11461145
}
@@ -6437,15 +6436,9 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
64376436
LITERAL_STR(opline->op1, lcname);
64386437

64396438
if (decl->flags & ZEND_ACC_ANON_CLASS) {
6439+
opline->opcode = ZEND_DECLARE_ANON_CLASS;
64406440
opline->result_type = IS_VAR;
64416441
opline->result.var = get_temporary_variable();
6442-
if (extends_ast) {
6443-
opline->opcode = ZEND_DECLARE_ANON_INHERITED_CLASS;
6444-
opline->op2_type = IS_CONST;
6445-
opline->op2.constant = zend_add_class_name_literal(zend_string_copy(ce->parent_name));
6446-
} else {
6447-
opline->opcode = ZEND_DECLARE_ANON_CLASS;
6448-
}
64496442

64506443
if (!zend_hash_add_ptr(CG(class_table), lcname, ce)) {
64516444
/* this anonymous class has been included */
@@ -6461,22 +6454,16 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
64616454
zend_add_literal_string(&key);
64626455
zend_hash_update_ptr(CG(class_table), key, ce);
64636456

6464-
if (extends_ast) {
6465-
if (toplevel
6457+
opline->opcode = ZEND_DECLARE_CLASS;
6458+
if (extends_ast && toplevel
64666459
&& (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
64676460
/* We currently don't early-bind classes that implement interfaces or use traits */
6468-
&& !(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
6469-
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
6470-
opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
6471-
opline->result_type = IS_UNUSED;
6472-
opline->result.opline_num = -1;
6473-
} else {
6474-
opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
6475-
}
6476-
opline->op2_type = IS_CONST;
6477-
opline->op2.constant = zend_add_class_name_literal(zend_string_copy(ce->parent_name));
6478-
} else {
6479-
opline->opcode = ZEND_DECLARE_CLASS;
6461+
&& !(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))
6462+
) {
6463+
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
6464+
opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
6465+
opline->result_type = IS_UNUSED;
6466+
opline->result.opline_num = -1;
64806467
}
64816468
}
64826469
return opline;

Zend/zend_compile.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ typedef struct _zend_oparray_context {
291291
#define ZEND_ACC_HAS_FINALLY_BLOCK (1 << 15) /* | X | | */
292292
/* | | | */
293293
/* "main" op_array with | | | */
294-
/* ZEND_DECLARE_INHERITED_CLASS_DELAYED opcodes | | | */
294+
/* ZEND_DECLARE_CLASS_DELAYED opcodes | | | */
295295
#define ZEND_ACC_EARLY_BINDING (1 << 16) /* | X | | */
296296
/* | | | */
297297
/* method flag (bc only), any method that has this | | | */
@@ -745,7 +745,7 @@ zend_bool zend_handle_encoding_declaration(zend_ast *ast);
745745
void zend_do_free(znode *op1);
746746

747747
ZEND_API int do_bind_function(zval *lcname);
748-
ZEND_API int do_bind_class(zval *lcname, zend_class_entry *parent_ce);
748+
ZEND_API int do_bind_class(zval *lcname);
749749
ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array);
750750
ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint32_t first_early_binding_opline);
751751

@@ -1032,7 +1032,7 @@ END_EXTERN_C()
10321032
* may apper in run-time */
10331033
#define ZEND_COMPILE_IGNORE_INTERNAL_CLASSES (1<<4)
10341034

1035-
/* generate ZEND_DECLARE_INHERITED_CLASS_DELAYED opcode to delay early binding */
1035+
/* generate ZEND_DECLARE_CLASS_DELAYED opcode to delay early binding */
10361036
#define ZEND_COMPILE_DELAYED_BINDING (1<<5)
10371037

10381038
/* disable constant substitution at compile-time */

Zend/zend_inheritance.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,10 +2130,11 @@ void zend_verify_abstract_class(zend_class_entry *ce) /* {{{ */
21302130
}
21312131
/* }}} */
21322132

2133-
ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent) /* {{{ */
2133+
ZEND_API void zend_do_link_class(zend_class_entry *ce) /* {{{ */
21342134
{
21352135
ce->ce_flags |= ZEND_ACC_LINKING_IN_PROGRESS;
2136-
if (parent) {
2136+
if (ce->parent_name) {
2137+
zend_class_entry *parent = zend_fetch_class_by_name(ce->parent_name, NULL, 0);
21372138
zend_do_inheritance(ce, parent);
21382139
}
21392140
if (ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS) {

Zend/zend_inheritance.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ BEGIN_EXTERN_C()
2727
ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface);
2828
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce);
2929

30-
ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_class_entry *parent_ce);
30+
ZEND_API void zend_do_link_class(zend_class_entry *ce);
3131

3232
void zend_verify_abstract_class(zend_class_entry *ce);
3333
void zend_check_deprecated_constructor(const zend_class_entry *ce);

Zend/zend_opcode.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,6 @@ static void emit_live_range(
585585
/* Classes don't have to be destroyed. */
586586
case ZEND_FETCH_CLASS:
587587
case ZEND_DECLARE_ANON_CLASS:
588-
case ZEND_DECLARE_ANON_INHERITED_CLASS:
589588
/* FAST_CALLs don't have to be destroyed. */
590589
case ZEND_FAST_CALL:
591590
return;
@@ -957,7 +956,6 @@ ZEND_API int pass_two(zend_op_array *op_array)
957956
break;
958957
}
959958
case ZEND_DECLARE_ANON_CLASS:
960-
case ZEND_DECLARE_ANON_INHERITED_CLASS:
961959
case ZEND_FE_FETCH_R:
962960
case ZEND_FE_FETCH_RW:
963961
/* absolute index to relative offset */

Zend/zend_vm_def.h

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7026,45 +7026,20 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY)
70267026
USE_OPLINE
70277027

70287028
SAVE_OPLINE();
7029-
do_bind_class(RT_CONSTANT(opline, opline->op1), NULL);
7029+
do_bind_class(RT_CONSTANT(opline, opline->op1));
70307030
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
70317031
}
70327032

7033-
ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, CONST, CONST)
7034-
{
7035-
zend_class_entry *parent;
7036-
USE_OPLINE
7037-
7038-
SAVE_OPLINE();
7039-
parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
7040-
Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1),
7041-
ZEND_FETCH_CLASS_EXCEPTION);
7042-
if (UNEXPECTED(parent == NULL)) {
7043-
ZEND_ASSERT(EG(exception));
7044-
HANDLE_EXCEPTION();
7045-
}
7046-
do_bind_class(RT_CONSTANT(opline, opline->op1), parent);
7047-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7048-
}
7049-
7050-
ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, CONST, CONST)
7033+
ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, ANY)
70517034
{
70527035
USE_OPLINE
70537036
zval *zce, *orig_zce;
7054-
zend_class_entry *parent;
70557037

70567038
SAVE_OPLINE();
70577039
if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
70587040
((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
70597041
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
7060-
parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
7061-
Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1),
7062-
ZEND_FETCH_CLASS_EXCEPTION);
7063-
if (UNEXPECTED(parent == NULL)) {
7064-
ZEND_ASSERT(EG(exception));
7065-
HANDLE_EXCEPTION();
7066-
}
7067-
do_bind_class(RT_CONSTANT(opline, opline->op1), parent);
7042+
do_bind_class(RT_CONSTANT(opline, opline->op1));
70687043
}
70697044
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
70707045
}
@@ -7085,36 +7060,7 @@ ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY, JMP_ADDR)
70857060
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
70867061
ZEND_VM_CONTINUE();
70877062
}
7088-
zend_do_link_class(ce, NULL);
7089-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7090-
}
7091-
7092-
ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, CONST, CONST, JMP_ADDR)
7093-
{
7094-
zval *zv;
7095-
zend_class_entry *ce, *parent;
7096-
USE_OPLINE
7097-
7098-
SAVE_OPLINE();
7099-
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
7100-
ZEND_ASSERT(zv != NULL);
7101-
ce = Z_CE_P(zv);
7102-
Z_CE_P(EX_VAR(opline->result.var)) = ce;
7103-
7104-
if (ce->ce_flags & ZEND_ACC_LINKED) {
7105-
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7106-
ZEND_VM_CONTINUE();
7107-
}
7108-
7109-
parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
7110-
Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1),
7111-
ZEND_FETCH_CLASS_EXCEPTION);
7112-
if (UNEXPECTED(parent == NULL)) {
7113-
ZEND_ASSERT(EG(exception));
7114-
HANDLE_EXCEPTION();
7115-
}
7116-
7117-
zend_do_link_class(ce, parent);
7063+
zend_do_link_class(ce);
71187064
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
71197065
}
71207066

@@ -7310,7 +7256,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
73107256

73117257
case ZEND_FETCH_CLASS:
73127258
case ZEND_DECLARE_ANON_CLASS:
7313-
case ZEND_DECLARE_ANON_INHERITED_CLASS:
73147259
break; /* return value is zend_class_entry pointer */
73157260

73167261
default:

0 commit comments

Comments
 (0)