From 0d054f5fafeeadb40edbf62a9bdae635965b5b5c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 2 Jun 2015 12:01:34 +0300 Subject: [PATCH] Avoid useless duplication. Constant values have to be duplicated only for internal constants in ZTS build, to prevent simultaneous modification of reference counters from different threads. --- Zend/zend_vm_def.h | 104 ++++++++------ Zend/zend_vm_execute.h | 312 +++++++++++++++++++++++------------------ 2 files changed, 232 insertions(+), 184 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0ecf1c10ba..12c82282e5 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5054,7 +5054,6 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) SAVE_OPLINE(); if (OP1_TYPE == IS_UNUSED) { zend_constant *c; - zval *retval; if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); @@ -5080,67 +5079,80 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); } - retval = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(retval, &c->value); - if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { - if (Z_OPT_COPYABLE_P(retval)) { - zval_copy_ctor_func(retval); - } else { - Z_ADDREF_P(retval); - } +#ifdef ZTS + if (c->flags & CONST_PERSISTENT) { + ZVAL_DUP(EX_VAR(opline->result.var), &c->value); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); +#endif } else { /* class constant */ zend_class_entry *ce; zval *value; - if (OP1_TYPE == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { - value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - ZEND_VM_C_GOTO(constant_fetch_end); - } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (OP1_TYPE == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); + ZVAL_DEREF(value); +#ifdef ZTS + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); +#endif + break; + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - if (UNEXPECTED(ce == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); - HANDLE_EXCEPTION(); + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { + ZVAL_DEREF(value); + break; } - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - ZEND_VM_C_GOTO(constant_fetch_end); - } - } - if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - ZVAL_DEREF(value); - if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; - } - if (OP1_TYPE == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { + ZVAL_DEREF(value); + if (Z_CONSTANT_P(value)) { + EG(scope) = ce; + zval_update_constant_ex(value, 1, NULL); + EG(scope) = EX(func)->op_array.scope; + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + if (OP1_TYPE == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + } } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } + } while (0); +#ifdef ZTS + if (ce->type == ZEND_INTERNAL_CLASS) { ZVAL_DUP(EX_VAR(opline->result.var), value); } else { - zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + ZVAL_COPY(EX_VAR(opline->result.var), value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), value); +#endif } -ZEND_VM_C_LABEL(constant_fetch_end): - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4b101e0b70..4c9a382fe7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5923,7 +5923,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS SAVE_OPLINE(); if (IS_CONST == IS_UNUSED) { zend_constant *c; - zval *retval; if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); @@ -5949,67 +5948,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); } - retval = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(retval, &c->value); - if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { - if (Z_OPT_COPYABLE_P(retval)) { - zval_copy_ctor_func(retval); - } else { - Z_ADDREF_P(retval); - } +#ifdef ZTS + if (c->flags & CONST_PERSISTENT) { + ZVAL_DUP(EX_VAR(opline->result.var), &c->value); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); +#endif } else { /* class constant */ zend_class_entry *ce; zval *value; - if (IS_CONST == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { - value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CONST == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); + ZVAL_DEREF(value); +#ifdef ZTS + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); +#endif + break; + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - if (UNEXPECTED(ce == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); - HANDLE_EXCEPTION(); + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { + ZVAL_DEREF(value); + break; } - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); - } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; } - } - if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - ZVAL_DEREF(value); - if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; - } - if (IS_CONST == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { + ZVAL_DEREF(value); + if (Z_CONSTANT_P(value)) { + EG(scope) = ce; + zval_update_constant_ex(value, 1, NULL); + EG(scope) = EX(func)->op_array.scope; + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + if (IS_CONST == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + } } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } + } while (0); +#ifdef ZTS + if (ce->type == ZEND_INTERNAL_CLASS) { ZVAL_DUP(EX_VAR(opline->result.var), value); } else { - zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + ZVAL_COPY(EX_VAR(opline->result.var), value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), value); +#endif } -constant_fetch_end: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -17578,7 +17590,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_ SAVE_OPLINE(); if (IS_VAR == IS_UNUSED) { zend_constant *c; - zval *retval; if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); @@ -17604,67 +17615,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_ } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); } - retval = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(retval, &c->value); - if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { - if (Z_OPT_COPYABLE_P(retval)) { - zval_copy_ctor_func(retval); - } else { - Z_ADDREF_P(retval); - } +#ifdef ZTS + if (c->flags & CONST_PERSISTENT) { + ZVAL_DUP(EX_VAR(opline->result.var), &c->value); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); +#endif } else { /* class constant */ zend_class_entry *ce; zval *value; - if (IS_VAR == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { - value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_VAR == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); + ZVAL_DEREF(value); +#ifdef ZTS + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); +#endif + break; + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - if (UNEXPECTED(ce == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); - HANDLE_EXCEPTION(); + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { + ZVAL_DEREF(value); + break; } - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } - } - if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - ZVAL_DEREF(value); - if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; - } - if (IS_VAR == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { + ZVAL_DEREF(value); + if (Z_CONSTANT_P(value)) { + EG(scope) = ce; + zval_update_constant_ex(value, 1, NULL); + EG(scope) = EX(func)->op_array.scope; + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + if (IS_VAR == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + } } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } + } while (0); +#ifdef ZTS + if (ce->type == ZEND_INTERNAL_CLASS) { ZVAL_DUP(EX_VAR(opline->result.var), value); } else { - zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + ZVAL_COPY(EX_VAR(opline->result.var), value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), value); +#endif } -constant_fetch_end: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -23995,7 +24019,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON SAVE_OPLINE(); if (IS_UNUSED == IS_UNUSED) { zend_constant *c; - zval *retval; if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); @@ -24021,67 +24044,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON } else { CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c); } - retval = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(retval, &c->value); - if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) { - if (Z_OPT_COPYABLE_P(retval)) { - zval_copy_ctor_func(retval); - } else { - Z_ADDREF_P(retval); - } +#ifdef ZTS + if (c->flags & CONST_PERSISTENT) { + ZVAL_DUP(EX_VAR(opline->result.var), &c->value); + } else { + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), &c->value); +#endif } else { /* class constant */ zend_class_entry *ce; zval *value; - if (IS_UNUSED == IS_CONST) { - if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { - value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { - ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); - } else { - ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_UNUSED == IS_CONST) { + if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) { + value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))); + ZVAL_DEREF(value); +#ifdef ZTS + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); +#endif + break; + } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) { + ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))); + } else { + ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + if (UNEXPECTED(ce == NULL)) { + zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); + HANDLE_EXCEPTION(); + } + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - if (UNEXPECTED(ce == NULL)) { - zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1))); - HANDLE_EXCEPTION(); + } else { + ce = Z_CE_P(EX_VAR(opline->op1.var)); + if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { + ZVAL_DEREF(value); + break; } - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce); } - } else { - ce = Z_CE_P(EX_VAR(opline->op1.var)); - if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) { - ZVAL_DEREF(value); - ZVAL_DUP(EX_VAR(opline->result.var), value); - goto constant_fetch_end; - } - } - if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { - ZVAL_DEREF(value); - if (Z_CONSTANT_P(value)) { - EG(scope) = ce; - zval_update_constant_ex(value, 1, NULL); - EG(scope) = EX(func)->op_array.scope; - } - if (IS_UNUSED == IS_CONST) { - CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) { + ZVAL_DEREF(value); + if (Z_CONSTANT_P(value)) { + EG(scope) = ce; + zval_update_constant_ex(value, 1, NULL); + EG(scope) = EX(func)->op_array.scope; + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + if (IS_UNUSED == IS_CONST) { + CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value); + } else { + CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + } } else { - CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value); + zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + HANDLE_EXCEPTION(); } + } while (0); +#ifdef ZTS + if (ce->type == ZEND_INTERNAL_CLASS) { ZVAL_DUP(EX_VAR(opline->result.var), value); } else { - zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2))); + ZVAL_COPY(EX_VAR(opline->result.var), value); } +#else + ZVAL_COPY(EX_VAR(opline->result.var), value); +#endif } -constant_fetch_end: - CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -- 2.50.1