Keep lowercased parent class name as second argument of DECLARE_CLASS to avoid extra work at run-time

This commit is contained in:
Dmitry Stogov 2019-06-25 11:26:29 +03:00
parent 43dd1ac570
commit 759f4ecd8b
8 changed files with 29 additions and 15 deletions

View File

@ -1057,7 +1057,7 @@ ZEND_API int do_bind_function(zval *lcname) /* {{{ */
} }
/* }}} */ /* }}} */
ZEND_API int do_bind_class(zval *lcname) /* {{{ */ ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name) /* {{{ */
{ {
zend_class_entry *ce; zend_class_entry *ce;
zval *rtd_key, *zv; zval *rtd_key, *zv;
@ -1084,7 +1084,7 @@ ZEND_API int do_bind_class(zval *lcname) /* {{{ */
return FAILURE; return FAILURE;
} }
zend_do_link_class(ce); zend_do_link_class(ce, lc_parent_name);
return SUCCESS; return SUCCESS;
} }
/* }}} */ /* }}} */
@ -1151,9 +1151,11 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint3
const zend_op *opline = &op_array->opcodes[opline_num]; const zend_op *opline = &op_array->opcodes[opline_num];
zval *lcname = RT_CONSTANT(opline, opline->op1); zval *lcname = RT_CONSTANT(opline, opline->op1);
zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname + 1)); zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), Z_STR_P(lcname + 1));
zend_class_entry *parent_ce = zend_lookup_class(ce->parent_name); zend_string *lc_parent_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
zend_class_entry *parent_ce = zend_lookup_class_ex(ce->parent_name, lc_parent_name, 0);
if (ce && parent_ce && zend_can_early_bind(ce, parent_ce)) { if (ce && parent_ce && zend_can_early_bind(ce, parent_ce)) {
do_bind_class(lcname); do_bind_class(lcname, lc_parent_name);
} }
opline_num = op_array->opcodes[opline_num].result.opline_num; opline_num = op_array->opcodes[opline_num].result.opline_num;
} }
@ -6458,6 +6460,13 @@ zend_op *zend_compile_class_decl(zend_ast *ast, zend_bool toplevel) /* {{{ */
opline = get_next_op(); opline = get_next_op();
if (ce->parent_name) {
/* Lowercased parent name */
zend_string *lc_parent_name = zend_string_tolower(ce->parent_name);
opline->op2_type = IS_CONST;
LITERAL_STR(opline->op2, lc_parent_name);
}
opline->op1_type = IS_CONST; opline->op1_type = IS_CONST;
LITERAL_STR(opline->op1, lcname); LITERAL_STR(opline->op1, lcname);

View File

@ -751,7 +751,7 @@ zend_bool zend_handle_encoding_declaration(zend_ast *ast);
void zend_do_free(znode *op1); void zend_do_free(znode *op1);
ZEND_API int do_bind_function(zval *lcname); ZEND_API int do_bind_function(zval *lcname);
ZEND_API int do_bind_class(zval *lcname); ZEND_API int do_bind_class(zval *lcname, zend_string *lc_parent_name);
ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array); ZEND_API uint32_t zend_build_delayed_early_binding_list(const zend_op_array *op_array);
ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint32_t first_early_binding_opline); ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint32_t first_early_binding_opline);

View File

@ -2362,11 +2362,11 @@ static void report_variance_errors(zend_class_entry *ce) {
zend_hash_index_del(all_obligations, num_key); zend_hash_index_del(all_obligations, num_key);
} }
ZEND_API void zend_do_link_class(zend_class_entry *ce) /* {{{ */ ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name) /* {{{ */
{ {
if (ce->parent_name) { if (ce->parent_name) {
zend_class_entry *parent = zend_fetch_class_by_name( zend_class_entry *parent = zend_fetch_class_by_name(
ce->parent_name, NULL, ZEND_FETCH_CLASS_ALLOW_UNLINKED); ce->parent_name, lc_parent_name, ZEND_FETCH_CLASS_ALLOW_UNLINKED);
if (!(parent->ce_flags & ZEND_ACC_LINKED)) { if (!(parent->ce_flags & ZEND_ACC_LINKED)) {
add_dependency_obligation(ce, parent); add_dependency_obligation(ce, parent);
} }

View File

@ -27,7 +27,7 @@ BEGIN_EXTERN_C()
ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface); ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface);
ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce); ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce);
ZEND_API void zend_do_link_class(zend_class_entry *ce); ZEND_API void zend_do_link_class(zend_class_entry *ce, zend_string *lc_parent_name);
void zend_verify_abstract_class(zend_class_entry *ce); void zend_verify_abstract_class(zend_class_entry *ce);
void zend_check_deprecated_constructor(const zend_class_entry *ce); void zend_check_deprecated_constructor(const zend_class_entry *ce);

View File

@ -7030,7 +7030,7 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY)
USE_OPLINE USE_OPLINE
SAVE_OPLINE(); SAVE_OPLINE();
do_bind_class(RT_CONSTANT(opline, opline->op1)); do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} }
@ -7043,7 +7043,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, ANY)
if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL || if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL && ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
Z_CE_P(zce) != Z_CE_P(orig_zce))) { Z_CE_P(zce) != Z_CE_P(orig_zce))) {
do_bind_class(RT_CONSTANT(opline, opline->op1)); do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
} }
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} }
@ -7064,7 +7064,7 @@ ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY, JMP_ADDR)
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
ZEND_VM_CONTINUE(); ZEND_VM_CONTINUE();
} }
zend_do_link_class(ce); zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} }

View File

@ -2111,7 +2111,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLE
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
ZEND_VM_CONTINUE(); ZEND_VM_CONTINUE();
} }
zend_do_link_class(ce); zend_do_link_class(ce, (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} }
@ -4022,7 +4022,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDL
USE_OPLINE USE_OPLINE
SAVE_OPLINE(); SAVE_OPLINE();
do_bind_class(RT_CONSTANT(opline, opline->op1)); do_bind_class(RT_CONSTANT(opline, opline->op1), (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} }
@ -4035,7 +4035,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_DELAYED_SPEC_CON
if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL || if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL && ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
Z_CE_P(zce) != Z_CE_P(orig_zce))) { Z_CE_P(zce) != Z_CE_P(orig_zce))) {
do_bind_class(RT_CONSTANT(opline, opline->op1)); do_bind_class(RT_CONSTANT(opline, opline->op1), (opline->op2_type == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
} }
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} }

View File

@ -270,9 +270,14 @@ literals_handle_static_prop:
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1);
break; break;
case ZEND_DECLARE_FUNCTION: case ZEND_DECLARE_FUNCTION:
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2);
break;
case ZEND_DECLARE_CLASS: case ZEND_DECLARE_CLASS:
case ZEND_DECLARE_CLASS_DELAYED: case ZEND_DECLARE_CLASS_DELAYED:
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2); LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2);
if (opline->op2_type == IS_CONST) {
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1);
}
break; break;
case ZEND_ISSET_ISEMPTY_DIM_OBJ: case ZEND_ISSET_ISEMPTY_DIM_OBJ:
case ZEND_ASSIGN_DIM: case ZEND_ASSIGN_DIM:

View File

@ -3582,7 +3582,7 @@ static void preload_link(void)
} else { } else {
CG(zend_lineno) = ce->info.user.line_start; CG(zend_lineno) = ce->info.user.line_start;
} }
zend_do_link_class(ce); zend_do_link_class(ce, NULL);
CG(in_compilation) = 0; CG(in_compilation) = 0;
CG(compiled_filename) = NULL; CG(compiled_filename) = NULL;