]> granicus.if.org Git - php/commitdiff
Avoid useless duplication. Constant values have to be duplicated only for internal...
authorDmitry Stogov <dmitry@zend.com>
Tue, 2 Jun 2015 09:01:34 +0000 (12:01 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 2 Jun 2015 09:01:34 +0000 (12:01 +0300)
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 0ecf1c10ba2bc2fb75f60c4a020717d1fa499d57..12c82282e5b65ed2ec0fdf865d6758b1d1be49cc 100644 (file)
@@ -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();
 }
 
index 4b101e0b70be559c8ee832e5318c1e75868a6bed..4c9a382fe7fd0a362b76140aa24e374b3c5cd297 100644 (file)
@@ -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();
 }