diff options
-rw-r--r-- | UPGRADING.INTERNALS | 8 | ||||
-rw-r--r-- | Zend/zend_compile.c | 76 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 68 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 208 | ||||
-rw-r--r-- | Zend/zend_vm_handlers.h | 8 | ||||
-rw-r--r-- | Zend/zend_vm_opcodes.c | 8 | ||||
-rw-r--r-- | ext/opcache/Optimizer/compact_literals.c | 9 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 5 |
8 files changed, 207 insertions, 183 deletions
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index b69d8216f6..101de4216e 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -24,6 +24,7 @@ PHP 7.3 INTERNALS UPGRADE NOTES u. GC_G v. php_add[c]slashes w. zend_class_entry.iterator_funcs + x. Class declaration opcodes (DECLARE_INHERITED_CLASS ...) 2. Build system changes a. Unix build system changes @@ -152,6 +153,13 @@ PHP 7.3 INTERNALS UPGRADE NOTES You don't have to set its value, setting parent.funcs in the get_iterator function is enough. + x. Class declaration opcode formats were changed + - DECLARE_INHERITED_CLASS and DECLARE_ANON_INHERITED_CLASS now encode parent + class name in second operand directly (as IS_CONST operand). Previously, + parent class was fetched but previous FETCH_CLASS opcode. + - ADD_INTERFACE and ADD_TRAIT don't use run-time cache to keep interface or + trait. These instructions are executed once, and caching is useless. + ======================== 2. Build system changes ======================== diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index bb0fb1159d..fa879c8d3c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1182,11 +1182,10 @@ void zend_do_early_binding(void) /* {{{ */ break; case ZEND_DECLARE_INHERITED_CLASS: { - zend_op *fetch_class_opline = opline-1; zval *parent_name; zend_class_entry *ce; - parent_name = CT_CONSTANT(fetch_class_opline->op2); + parent_name = CT_CONSTANT(opline->op2); if (((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) == NULL) || ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) && (ce->type == ZEND_INTERNAL_CLASS))) { @@ -1201,9 +1200,8 @@ void zend_do_early_binding(void) /* {{{ */ if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), ce, 1) == NULL) { return; } - /* clear unnecessary ZEND_FETCH_CLASS opcode */ - zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant); - MAKE_NOP(fetch_class_opline); + zend_del_literal(CG(active_op_array), opline->op2.constant+1); + zend_del_literal(CG(active_op_array), opline->op2.constant); table = CG(class_table); break; @@ -1287,7 +1285,7 @@ ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array, uint3 CG(in_compilation) = 1; while (opline_num != (uint32_t)-1) { - const zend_op *opline = &op_array->opcodes[opline_num-1]; + const zend_op *opline = &op_array->opcodes[opline_num]; zval *parent_name = RT_CONSTANT(opline, opline->op2); if ((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) != NULL) { do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0); @@ -2462,46 +2460,6 @@ static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) / } /* }}} */ -static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int throw_exception) /* {{{ */ -{ - zend_op *opline; - znode name_node; - zend_compile_expr(&name_node, name_ast); - - if (name_node.op_type == IS_CONST) { - zend_string *name; - uint32_t fetch_type; - - if (Z_TYPE(name_node.u.constant) != IS_STRING) { - zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name"); - } - - name = Z_STR(name_node.u.constant); - fetch_type = zend_get_class_fetch_type(name); - - opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, NULL); - opline->op1.num = fetch_type | (throw_exception ? ZEND_FETCH_CLASS_EXCEPTION : 0); - - if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { - uint32_t type = name_ast->kind == ZEND_AST_ZVAL ? name_ast->attr : ZEND_NAME_FQ; - opline->op2_type = IS_CONST; - opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), - zend_resolve_class_name(name, type)); - opline->extended_value = zend_alloc_cache_slot(); - } else { - zend_ensure_valid_class_fetch_type(fetch_type); - } - - zend_string_release_ex(name, 0); - } else { - opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node); - opline->op1.num = ZEND_FETCH_CLASS_DEFAULT | (throw_exception ? ZEND_FETCH_CLASS_EXCEPTION : 0); - } - - return opline; -} -/* }}} */ - static void zend_compile_class_ref_ex(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */ { uint32_t fetch_type; @@ -6274,7 +6232,6 @@ void zend_compile_use_trait(zend_ast *ast) /* {{{ */ opline->op2_type = IS_CONST; opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), zend_resolve_class_name_ast(trait_ast)); - opline->extended_value = zend_alloc_cache_slot(); ce->num_traits++; } @@ -6317,7 +6274,6 @@ void zend_compile_implements(znode *class_node, zend_ast *ast) /* {{{ */ opline->op2_type = IS_CONST; opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), zend_resolve_class_name_ast(class_ast)); - opline->extended_value = zend_alloc_cache_slot(); CG(active_class_entry)->num_interfaces++; } @@ -6347,7 +6303,8 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ zend_string *name, *lcname; zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry)); zend_op *opline; - znode declare_node, extends_node; + znode declare_node; + int extends_const; zend_class_entry *original_ce = CG(active_class_entry); znode original_implementing_class = FC(implementing_class); @@ -6400,13 +6357,24 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ } if (extends_ast) { + znode extends_node; + zend_string *extends_name; + if (!zend_is_const_default_class_ref(extends_ast)) { - zend_string *extends_name = zend_ast_get_str(extends_ast); + extends_name = zend_ast_get_str(extends_ast); zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", ZSTR_VAL(extends_name)); } - zend_compile_class_ref(&extends_node, extends_ast, 1); + zend_compile_expr(&extends_node, extends_ast); + if (extends_node.op_type != IS_CONST || Z_TYPE(extends_node.u.constant) != IS_STRING) { + zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name"); + } + extends_name = Z_STR(extends_node.u.constant); + extends_const = zend_add_class_name_literal(CG(active_op_array), + zend_resolve_class_name(extends_name, + extends_ast->kind == ZEND_AST_ZVAL ? extends_ast->attr : ZEND_NAME_FQ)); + zend_string_release_ex(extends_name, 0); ce->ce_flags |= ZEND_ACC_INHERITED; } @@ -6421,7 +6389,8 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ if (decl->flags & ZEND_ACC_ANON_CLASS) { if (extends_ast) { opline->opcode = ZEND_DECLARE_ANON_INHERITED_CLASS; - SET_NODE(opline->op2, &extends_node); + opline->op2_type = IS_CONST; + opline->op2.constant = extends_const; } else { opline->opcode = ZEND_DECLARE_ANON_CLASS; } @@ -6440,7 +6409,8 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ if (extends_ast) { opline->opcode = ZEND_DECLARE_INHERITED_CLASS; - SET_NODE(opline->op2, &extends_node); + opline->op2_type = IS_CONST; + opline->op2.constant = extends_const; } else { opline->opcode = ZEND_DECLARE_CLASS; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 41fcb9d24d..57c4ff8c79 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6622,7 +6622,7 @@ ZEND_VM_COLD_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY) +ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY) { USE_OPLINE @@ -6631,25 +6631,41 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, VAR) +ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, CONST, CONST) { + zend_class_entry *parent; USE_OPLINE SAVE_OPLINE(); - Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->op2.var)), 0); + parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(parent == NULL)) { + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), parent, 0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, VAR) +ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, CONST, CONST) { USE_OPLINE zval *zce, *orig_zce; + zend_class_entry *parent; SAVE_OPLINE(); 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 && Z_CE_P(zce) != Z_CE_P(orig_zce))) { - do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->op2.var)), 0); + parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(parent == NULL)) { + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), parent, 0); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -6678,10 +6694,10 @@ ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY, JMP_ADDR) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, ANY, VAR, JMP_ADDR) +ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, CONST, CONST, JMP_ADDR) { zval *zv; - zend_class_entry *ce; + zend_class_entry *ce, *parent; USE_OPLINE SAVE_OPLINE(); @@ -6695,7 +6711,15 @@ ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, ANY, VAR, JMP_ADDR) ZEND_VM_CONTINUE(); } - zend_do_inheritance(ce, Z_CE_P(EX_VAR(opline->op2.var))); + parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(parent == NULL)) { + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + + zend_do_inheritance(ce, parent); ce->ce_flags |= ZEND_ACC_ANON_BOUND; ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -6794,13 +6818,10 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST, CACHE_SLOT) zend_class_entry *iface; SAVE_OPLINE(); - iface = CACHED_PTR(opline->extended_value); + iface = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE); if (UNEXPECTED(iface == NULL)) { - iface = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE); - if (UNEXPECTED(iface == NULL)) { - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - CACHE_PTR(opline->extended_value, iface); + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); } if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) { @@ -6818,18 +6839,15 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY, CACHE_SLOT) zend_class_entry *trait; SAVE_OPLINE(); - trait = CACHED_PTR(opline->extended_value); + trait = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_TRAIT); if (UNEXPECTED(trait == NULL)) { - trait = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), - RT_CONSTANT(opline, opline->op2) + 1, - ZEND_FETCH_CLASS_TRAIT); - if (UNEXPECTED(trait == NULL)) { - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - if (!(trait->ce_flags & ZEND_ACC_TRAIT)) { - zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name)); - } - CACHE_PTR(opline->extended_value, trait); + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + if (!(trait->ce_flags & ZEND_ACC_TRAIT)) { + zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name)); } zend_do_implement_trait(ce, trait); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e279aca674..8c2e7ee7c2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1584,15 +1584,6 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXT_FCALL_END_SPE ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - SAVE_OPLINE(); - Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zval *zv; @@ -1662,18 +1653,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OP zend_class_entry *trait; SAVE_OPLINE(); - trait = CACHED_PTR(opline->extended_value); + trait = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_TRAIT); if (UNEXPECTED(trait == NULL)) { - trait = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), - RT_CONSTANT(opline, opline->op2) + 1, - ZEND_FETCH_CLASS_TRAIT); - if (UNEXPECTED(trait == NULL)) { - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - if (!(trait->ce_flags & ZEND_ACC_TRAIT)) { - zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name)); - } - CACHE_PTR(opline->extended_value, trait); + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + if (!(trait->ce_flags & ZEND_ACC_TRAIT)) { + zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name)); } zend_do_implement_trait(ce, trait); @@ -2277,13 +2265,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDL zend_class_entry *iface; SAVE_OPLINE(); - iface = CACHED_PTR(opline->extended_value); + iface = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE); if (UNEXPECTED(iface == NULL)) { - iface = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE); - if (UNEXPECTED(iface == NULL)) { - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); - } - CACHE_PTR(opline->extended_value, iface); + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); } if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) { @@ -2351,51 +2336,6 @@ try_function_name: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - - SAVE_OPLINE(); - Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->op2.var)), 0); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *zce, *orig_zce; - - SAVE_OPLINE(); - 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 && - Z_CE_P(zce) != Z_CE_P(orig_zce))) { - do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->op2.var)), 0); - } - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zval *zv; - zend_class_entry *ce; - USE_OPLINE - - SAVE_OPLINE(); - zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1); - ZEND_ASSERT(zv != NULL); - ce = Z_CE_P(zv); - Z_CE_P(EX_VAR(opline->result.var)) = ce; - - if (ce->ce_flags & ZEND_ACC_ANON_BOUND) { - ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); - ZEND_VM_CONTINUE(); - } - - zend_do_inheritance(ce, Z_CE_P(EX_VAR(opline->op2.var))); - ce->ce_flags |= ZEND_ACC_ANON_BOUND; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); -} - static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3673,6 +3613,15 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CON ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + SAVE_OPLINE(); + Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5879,6 +5828,75 @@ isset_no_object: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *parent; + USE_OPLINE + + SAVE_OPLINE(); + parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(parent == NULL)) { + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), parent, 0); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *zce, *orig_zce; + zend_class_entry *parent; + + SAVE_OPLINE(); + 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 && + Z_CE_P(zce) != Z_CE_P(orig_zce))) { + parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(parent == NULL)) { + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), parent, 0); + } + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *zv; + zend_class_entry *ce, *parent; + USE_OPLINE + + SAVE_OPLINE(); + zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1); + ZEND_ASSERT(zv != NULL); + ce = Z_CE_P(zv); + Z_CE_P(EX_VAR(opline->result.var)) = ce; + + if (ce->ce_flags & ZEND_ACC_ANON_BOUND) { + ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value); + ZEND_VM_CONTINUE(); + } + + parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), + RT_CONSTANT(opline, opline->op2) + 1, + ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(parent == NULL)) { + ZEND_ASSERT(EG(exception)); + HANDLE_EXCEPTION(); + } + + zend_do_inheritance(ce, parent); + ce->ce_flags |= ZEND_ACC_ANON_BOUND; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -53224,8 +53242,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_INSTANCEOF_SPEC_CV_VAR_LABEL, (void*)&&ZEND_INSTANCEOF_SPEC_CV_UNUSED_LABEL, (void*)&&ZEND_NULL_LABEL, - (void*)&&ZEND_DECLARE_CLASS_SPEC_LABEL, - (void*)&&ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_LABEL, + (void*)&&ZEND_DECLARE_CLASS_SPEC_CONST_LABEL, + (void*)&&ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_DECLARE_FUNCTION_SPEC_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_CONST_LABEL, (void*)&&ZEND_YIELD_FROM_SPEC_TMP_LABEL, @@ -53234,7 +53252,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_YIELD_FROM_SPEC_CV_LABEL, (void*)&&ZEND_DECLARE_CONST_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_ADD_INTERFACE_SPEC_CONST_LABEL, - (void*)&&ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_LABEL, + (void*)&&ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_VERIFY_ABSTRACT_CLASS_SPEC_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, @@ -53567,7 +53585,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_SPACESHIP_SPEC_CV_CV_LABEL, (void*)&&ZEND_DECLARE_ANON_CLASS_SPEC_LABEL, - (void*)&&ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_LABEL, + (void*)&&ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_VAR_LABEL, @@ -54945,10 +54963,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_EXT_FCALL_END_SPEC) ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_DECLARE_CLASS_SPEC): - VM_TRACE(ZEND_DECLARE_CLASS_SPEC) - ZEND_DECLARE_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_DECLARE_ANON_CLASS_SPEC): VM_TRACE(ZEND_DECLARE_ANON_CLASS_SPEC) ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55041,18 +55055,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR) ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR): - VM_TRACE(ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR) - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR): - VM_TRACE(ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR) - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); - HYBRID_CASE(ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR): - VM_TRACE(ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR) - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_RECV_SPEC_UNUSED): VM_TRACE(ZEND_RECV_SPEC_UNUSED) ZEND_RECV_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55235,6 +55237,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_QM_ASSIGN_SPEC_CONST) ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_CLASS_SPEC_CONST): + VM_TRACE(ZEND_DECLARE_CLASS_SPEC_CONST) + ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_YIELD_FROM_SPEC_CONST): VM_TRACE(ZEND_YIELD_FROM_SPEC_CONST) ZEND_YIELD_FROM_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -55439,6 +55445,18 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST) ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST): + VM_TRACE(ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST) + ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST): + VM_TRACE(ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST) + ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); + HYBRID_CASE(ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST): + VM_TRACE(ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST) + ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_DECLARE_CONST_SPEC_CONST_CONST): VM_TRACE(ZEND_DECLARE_CONST_SPEC_CONST_CONST) ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -62759,8 +62777,8 @@ void zend_vm_init(void) ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER, ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER, ZEND_NULL_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, + ZEND_DECLARE_CLASS_SPEC_CONST_HANDLER, + ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST_HANDLER, ZEND_DECLARE_FUNCTION_SPEC_HANDLER, ZEND_YIELD_FROM_SPEC_CONST_HANDLER, ZEND_YIELD_FROM_SPEC_TMP_HANDLER, @@ -62769,7 +62787,7 @@ void zend_vm_init(void) ZEND_YIELD_FROM_SPEC_CV_HANDLER, ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, + ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST_HANDLER, ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, @@ -63102,7 +63120,7 @@ void zend_vm_init(void) ZEND_NULL_HANDLER, ZEND_SPACESHIP_SPEC_CV_CV_HANDLER, ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, + ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST_HANDLER, ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_VAR_HANDLER, diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index f8493a02b1..9a674f4c56 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1238,8 +1238,8 @@ _(2423, ZEND_INSTANCEOF_SPEC_CV_CONST) \ _(2425, ZEND_INSTANCEOF_SPEC_CV_VAR) \ _(2426, ZEND_INSTANCEOF_SPEC_CV_UNUSED) \ - _(2428, ZEND_DECLARE_CLASS_SPEC) \ - _(2429, ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR) \ + _(2428, ZEND_DECLARE_CLASS_SPEC_CONST) \ + _(2429, ZEND_DECLARE_INHERITED_CLASS_SPEC_CONST_CONST) \ _(2430, ZEND_DECLARE_FUNCTION_SPEC) \ _(2431, ZEND_YIELD_FROM_SPEC_CONST) \ _(2432, ZEND_YIELD_FROM_SPEC_TMP) \ @@ -1247,7 +1247,7 @@ _(2435, ZEND_YIELD_FROM_SPEC_CV) \ _(2436, ZEND_DECLARE_CONST_SPEC_CONST_CONST) \ _(2437, ZEND_ADD_INTERFACE_SPEC_CONST) \ - _(2438, ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR) \ + _(2438, ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_CONST_CONST) \ _(2439, ZEND_VERIFY_ABSTRACT_CLASS_SPEC) \ _(2490, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST) \ _(2491, ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP) \ @@ -1424,7 +1424,7 @@ _(2767, ZEND_SPACESHIP_SPEC_CV_TMPVAR) \ _(2769, ZEND_SPACESHIP_SPEC_CV_CV) \ _(2770, ZEND_DECLARE_ANON_CLASS_SPEC) \ - _(2771, ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR) \ + _(2771, ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_CONST_CONST) \ _(2772, ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_CONST) \ _(2774, ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_VAR) \ _(2775, ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_UNUSED) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index f09efd50d6..73a2c164ea 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -364,13 +364,13 @@ static uint32_t zend_vm_opcodes_flags[199] = { 0x00040751, 0x00000000, 0x00047305, - 0x00000000, - 0x00000100, + 0x00000003, + 0x00000303, 0x00000000, 0x00000003, 0x00000303, 0x00040300, - 0x00000100, + 0x00000303, 0x00000000, 0x00006701, 0x00060757, @@ -397,7 +397,7 @@ static uint32_t zend_vm_opcodes_flags[199] = { 0x00002003, 0x00000707, 0x03000000, - 0x03000100, + 0x03000303, 0x00047307, 0x00047307, 0x00047307, diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c index f541561ae0..b70f5c2e28 100644 --- a/ext/opcache/Optimizer/compact_literals.c +++ b/ext/opcache/Optimizer/compact_literals.c @@ -261,9 +261,16 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx break; case ZEND_DECLARE_FUNCTION: case ZEND_DECLARE_CLASS: + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2); + break; case ZEND_DECLARE_INHERITED_CLASS: case ZEND_DECLARE_INHERITED_CLASS_DELAYED: LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2); + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); + break; + case ZEND_DECLARE_ANON_INHERITED_CLASS: + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 2); break; case ZEND_ISSET_ISEMPTY_DIM_OBJ: case ZEND_ASSIGN_DIM: @@ -738,8 +745,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } break; case ZEND_FETCH_CLASS: - case ZEND_ADD_INTERFACE: - case ZEND_ADD_TRAIT: case ZEND_INSTANCEOF: if (opline->op2_type == IS_CONST) { // op2 class diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 5c5dee01ab..3904a6d35a 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -392,6 +392,11 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, } case ZEND_ADD_INTERFACE: case ZEND_ADD_TRAIT: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op2.constant = zend_optimizer_add_literal(op_array, val); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + break; case ZEND_INSTANCEOF: REQUIRES_STRING(val); drop_leading_backslash(val); |