Skip to content

Commit 9cf7df0

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

24 files changed

+1211
-1395
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
}
@@ -6432,15 +6431,9 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
64326431
LITERAL_STR(opline->op1, lcname);
64336432

64346433
if (decl->flags & ZEND_ACC_ANON_CLASS) {
6434+
opline->opcode = ZEND_DECLARE_ANON_CLASS;
64356435
opline->result_type = IS_VAR;
64366436
opline->result.var = get_temporary_variable();
6437-
if (extends_ast) {
6438-
opline->opcode = ZEND_DECLARE_ANON_INHERITED_CLASS;
6439-
opline->op2_type = IS_CONST;
6440-
opline->op2.constant = zend_add_class_name_literal(zend_string_copy(ce->parent_name));
6441-
} else {
6442-
opline->opcode = ZEND_DECLARE_ANON_CLASS;
6443-
}
64446437

64456438
if (!zend_hash_add_ptr(CG(class_table), lcname, ce)) {
64466439
/* this anonymous class has been included */
@@ -6456,22 +6449,16 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
64566449
zend_add_literal_string(&key);
64576450
zend_hash_update_ptr(CG(class_table), key, ce);
64586451

6459-
if (extends_ast) {
6460-
if (toplevel
6452+
opline->opcode = ZEND_DECLARE_CLASS;
6453+
if (extends_ast && toplevel
64616454
&& (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING)
64626455
/* We currently don't early-bind classes that implement interfaces or use traits */
6463-
&& !(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
6464-
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
6465-
opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
6466-
opline->result_type = IS_UNUSED;
6467-
opline->result.opline_num = -1;
6468-
} else {
6469-
opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
6470-
}
6471-
opline->op2_type = IS_CONST;
6472-
opline->op2.constant = zend_add_class_name_literal(zend_string_copy(ce->parent_name));
6473-
} else {
6474-
opline->opcode = ZEND_DECLARE_CLASS;
6456+
&& !(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))
6457+
) {
6458+
CG(active_op_array)->fn_flags |= ZEND_ACC_EARLY_BINDING;
6459+
opline->opcode = ZEND_DECLARE_CLASS_DELAYED;
6460+
opline->result_type = IS_UNUSED;
6461+
opline->result.opline_num = -1;
64756462
}
64766463
}
64776464
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

@@ -1023,7 +1023,7 @@ END_EXTERN_C()
10231023
* may apper in run-time */
10241024
#define ZEND_COMPILE_IGNORE_INTERNAL_CLASSES (1<<4)
10251025

1026-
/* generate ZEND_DECLARE_INHERITED_CLASS_DELAYED opcode to delay early binding */
1026+
/* generate ZEND_DECLARE_CLASS_DELAYED opcode to delay early binding */
10271027
#define ZEND_COMPILE_DELAYED_BINDING (1<<5)
10281028

10291029
/* 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
@@ -7064,45 +7064,20 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY)
70647064
USE_OPLINE
70657065

70667066
SAVE_OPLINE();
7067-
do_bind_class(RT_CONSTANT(opline, opline->op1), NULL);
7067+
do_bind_class(RT_CONSTANT(opline, opline->op1));
70687068
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
70697069
}
70707070

7071-
ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, CONST, CONST)
7072-
{
7073-
zend_class_entry *parent;
7074-
USE_OPLINE
7075-
7076-
SAVE_OPLINE();
7077-
parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
7078-
Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1),
7079-
ZEND_FETCH_CLASS_EXCEPTION);
7080-
if (UNEXPECTED(parent == NULL)) {
7081-
ZEND_ASSERT(EG(exception));
7082-
HANDLE_EXCEPTION();
7083-
}
7084-
do_bind_class(RT_CONSTANT(opline, opline->op1), parent);
7085-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7086-
}
7087-
7088-
ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, CONST, CONST)
7071+
ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, ANY)
70897072
{
70907073
USE_OPLINE
70917074
zval *zce, *orig_zce;
7092-
zend_class_entry *parent;
70937075

70947076
SAVE_OPLINE();
70957077
if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
70967078
((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
70977079
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
7098-
parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
7099-
Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1),
7100-
ZEND_FETCH_CLASS_EXCEPTION);
7101-
if (UNEXPECTED(parent == NULL)) {
7102-
ZEND_ASSERT(EG(exception));
7103-
HANDLE_EXCEPTION();
7104-
}
7105-
do_bind_class(RT_CONSTANT(opline, opline->op1), parent);
7080+
do_bind_class(RT_CONSTANT(opline, opline->op1));
71067081
}
71077082
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
71087083
}
@@ -7123,36 +7098,7 @@ ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY, JMP_ADDR)
71237098
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
71247099
ZEND_VM_CONTINUE();
71257100
}
7126-
zend_do_link_class(ce, NULL);
7127-
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7128-
}
7129-
7130-
ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, CONST, CONST, JMP_ADDR)
7131-
{
7132-
zval *zv;
7133-
zend_class_entry *ce, *parent;
7134-
USE_OPLINE
7135-
7136-
SAVE_OPLINE();
7137-
zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
7138-
ZEND_ASSERT(zv != NULL);
7139-
ce = Z_CE_P(zv);
7140-
Z_CE_P(EX_VAR(opline->result.var)) = ce;
7141-
7142-
if (ce->ce_flags & ZEND_ACC_LINKED) {
7143-
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7144-
ZEND_VM_CONTINUE();
7145-
}
7146-
7147-
parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
7148-
Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1),
7149-
ZEND_FETCH_CLASS_EXCEPTION);
7150-
if (UNEXPECTED(parent == NULL)) {
7151-
ZEND_ASSERT(EG(exception));
7152-
HANDLE_EXCEPTION();
7153-
}
7154-
7155-
zend_do_link_class(ce, parent);
7101+
zend_do_link_class(ce);
71567102
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
71577103
}
71587104

@@ -7348,7 +7294,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
73487294

73497295
case ZEND_FETCH_CLASS:
73507296
case ZEND_DECLARE_ANON_CLASS:
7351-
case ZEND_DECLARE_ANON_INHERITED_CLASS:
73527297
break; /* return value is zend_class_entry pointer */
73537298

73547299
default:

0 commit comments

Comments
 (0)