summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UPGRADING.INTERNALS8
-rw-r--r--Zend/zend_compile.c76
-rw-r--r--Zend/zend_vm_def.h68
-rw-r--r--Zend/zend_vm_execute.h208
-rw-r--r--Zend/zend_vm_handlers.h8
-rw-r--r--Zend/zend_vm_opcodes.c8
-rw-r--r--ext/opcache/Optimizer/compact_literals.c9
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c5
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);