]> granicus.if.org Git - php/commitdiff
- in case of ambiguity class name in namespace call __autoload() only after
authorDmitry Stogov <dmitry@php.net>
Tue, 11 Sep 2007 11:23:12 +0000 (11:23 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 11 Sep 2007 11:23:12 +0000 (11:23 +0000)
  checking for both (class from current namespace and internal class)
- improved class fetching performance
- fixed wrong (lowercase) name passed to __autoload() from call_user_func()

Zend/zend_constants.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index de76ec3658696ce6594d344828ba52567b054048..85bbc5e7289d1221a93b904aa2744795cded0e7d 100644 (file)
@@ -333,7 +333,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z
        if ((UG(unicode) && (colon.u = u_memrchr(name.u, ':', name_len)) && colon.u > name.u && *(colon.u-1) == ':') ||
            (!UG(unicode) && (colon.s = zend_memrchr(name.s, ':', name_len))&& colon.s > name.s && *(colon.s-1) == ':')) {
                /* compound constant name */
-               zend_class_entry **ce = NULL;
+               zend_class_entry *ce = NULL;
                int class_name_len = UG(unicode)?colon.u-name.u-1:colon.s-name.s-1;
                int const_name_len = name_len - class_name_len - 2;
                zstr constant_name, class_name;
@@ -366,7 +366,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z
                if (lcname_len == sizeof("self")-1 &&
                    ZEND_U_EQUAL(type, lcname, lcname_len, "self", sizeof("self")-1)) {
                        if (scope) {
-                               ce = &scope;
+                               ce = scope;
                        } else {
                                zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
                                retval = 0;
@@ -379,7 +379,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z
                        } else if (!scope->parent) {
                                zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
                        } else {
-                               ce = &scope->parent;
+                               ce = scope->parent;
                        }
                        efree(lcname.v);
                } else {
@@ -427,31 +427,11 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z
                        efree(lcname.v);
 
                        /* Check for class */
-                       if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS &&
-                           (flags & ZEND_FETCH_CLASS_RT_NS_CHECK) != 0) {
-                               retval = 0;
-                               if ((UG(unicode) && (colon.u = u_memrchr(class_name.u, ':', class_name_len)) && colon.u > class_name.u && *(colon.u-1) == ':') ||
-                                   (!UG(unicode) && (colon.s = zend_memrchr(class_name.s, ':', class_name_len))&& colon.s > class_name.s && *(colon.s-1) == ':')) {
-
-                                       if (UG(unicode)) {
-                                               colon.u++;
-                                               lcname_len = class_name_len - (colon.u - class_name.u);
-                                       } else {
-                                               colon.s++;
-                                               lcname_len = class_name_len - (colon.s - class_name.s);
-                                       }
-                                       lcname = zend_u_str_case_fold(type, colon, lcname_len, 0, &lcname_len);
-                                       if (zend_u_hash_find(CG(class_table), type, lcname, lcname_len+1, (void**)&ce) == SUCCESS &&
-                                           (*ce)->type == ZEND_INTERNAL_CLASS) {
-                                               retval = 1;
-                                       }
-                                       efree(lcname.v);
-                               }
-                       }
+                       ce = zend_u_fetch_class(type, class_name, class_name_len, flags TSRMLS_CC);
                }
 
                if (retval && ce) {
-                       if (zend_u_hash_find(&((*ce)->constants_table), type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
+                       if (zend_u_hash_find(&ce->constants_table, type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
                                retval = 0;
                        }
                } else {
@@ -470,7 +450,7 @@ ZEND_API int zend_u_get_constant_ex(zend_uchar type, zstr name, uint name_len, z
                efree(class_name.v);
 
                if (retval) {
-                       zval_update_constant_ex(ret_constant, (void*)1, *ce TSRMLS_CC);
+                       zval_update_constant_ex(ret_constant, (void*)1, ce TSRMLS_CC);
                        *result = **ret_constant;
                        zval_copy_ctor(result);
                }
index a214475e90645e7c2c914f45778a6a2483487942..71b25fb5a78f75ccf4b8ef59dd5edf5ee3720e50 100644 (file)
@@ -76,9 +76,9 @@ static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LI
        }
 }
 ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
-ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC);
+ZEND_API int zend_lookup_class_ex(char *name, int name_length, char *autoload_name, zend_class_entry ***ce TSRMLS_DC);
 ZEND_API int zend_u_lookup_class(zend_uchar type, zstr name, int name_length, zend_class_entry ***ce TSRMLS_DC);
-ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, int use_autoload, int do_normalize, zend_class_entry ***ce TSRMLS_DC);
+ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, zstr autoload_name, int do_normalize, zend_class_entry ***ce TSRMLS_DC);
 ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
 ZEND_API int zend_u_eval_string(zend_uchar type, zstr str, zval *retval_ptr, char *string_name TSRMLS_DC);
index e80e5ba427cee613a8793255214977f8616fb36b..76c31ce7d1547b659b7528036d795201932d445a 100644 (file)
@@ -485,7 +485,6 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco
        zend_bool inline_change = (zend_bool) (zend_uintptr_t) arg;
        zval const_value;
        zstr colon;
-       int len;
 
        if (IS_CONSTANT_VISITED(p)) {
                zend_error(E_ERROR, "Cannot declare self-referencing constant '%v'", Z_UNIVAL_P(p));
@@ -853,7 +852,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                        } else if (calling_scope && clen == sizeof("parent") - 1 && 
                            ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "parent", sizeof("parent")-1)) {
                                ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
-                       } else if (zend_u_lookup_class_ex(Z_TYPE_P(fci->function_name), lcname, clen, 1, 0, &pce TSRMLS_CC) == SUCCESS) {
+                       } else if (zend_u_lookup_class_ex(Z_TYPE_P(fci->function_name), lcname, clen, Z_UNIVAL_P(fci->function_name), 0, &pce TSRMLS_CC) == SUCCESS) {
                                ce_child = *pce;
                        }
                        efree(lcname.v);
@@ -1126,7 +1125,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
 }
 /* }}} */
 
-ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, int use_autoload, int do_normalize, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
+ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length, zstr autoload_name, int do_normalize, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
 {
        zval **args[1];
        zval autoload_function;
@@ -1174,7 +1173,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
        /* The compiler is not-reentrant. Make sure we __autoload() only during run-time
         * (doesn't impact fuctionality of __autoload()
        */
-       if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
+       if (!autoload_name.v || zend_is_compiling(TSRMLS_C)) {
                if (do_normalize) {
                        efree(lc_free.v);
                }
@@ -1197,7 +1196,7 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
 
        ALLOC_ZVAL(class_name_ptr);
        INIT_PZVAL(class_name_ptr);
-       ZVAL_ZSTRL(class_name_ptr, type, name, name_length, 1);
+       ZVAL_ZSTR(class_name_ptr, type, autoload_name, 1);
 
        args[0] = &class_name_ptr;
 
@@ -1261,13 +1260,13 @@ ZEND_API int zend_u_lookup_class_ex(zend_uchar type, zstr name, int name_length,
 
 ZEND_API int zend_u_lookup_class(zend_uchar type, zstr name, int name_length, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
 {
-       return zend_u_lookup_class_ex(type, name, name_length, 1, 1, ce TSRMLS_CC);
+       return zend_u_lookup_class_ex(type, name, name_length, name, 1, ce TSRMLS_CC);
 }
 /* }}} */
 
-ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
+ZEND_API int zend_lookup_class_ex(char *name, int name_length, char *autoload_name, zend_class_entry ***ce TSRMLS_DC) /* {{{ */
 {
-       return zend_u_lookup_class_ex(IS_STRING, ZSTR(name), name_length, use_autoload, 1, ce TSRMLS_CC);
+       return zend_u_lookup_class_ex(IS_STRING, ZSTR(name), name_length, ZSTR(autoload_name), 1, ce TSRMLS_CC);
 }
 /* }}} */
 
@@ -1683,12 +1682,12 @@ check_fetch_type:
                case ZEND_FETCH_CLASS_AUTO: {
                                if (do_normalize) {
                                        lcname = zend_u_str_case_fold(type, class_name, class_name_len, 1, &class_name_len);
+                                       do_normalize = 0; /* we've normalized it already, don't do it twice */
                                }
                                fetch_type = zend_get_class_fetch_type(type, lcname, class_name_len);
                                if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
-                                       if (do_normalize) {
+                                       if (lcname.v != class_name.v) {
                                                efree(lcname.v);
-                                               do_normalize = 0; /* we've normalized it already, don't do it twice */
                                        }
                                        goto check_fetch_type;
                                }
@@ -1696,38 +1695,46 @@ check_fetch_type:
                        break;
        }
 
-       if (zend_u_lookup_class_ex(type, lcname, class_name_len, use_autoload, do_normalize, &pce TSRMLS_CC)==FAILURE) {
+       if (do_normalize) {
+               lcname = zend_u_str_case_fold(type, class_name, class_name_len, 1, &class_name_len);
+       }
+
+       if (zend_u_lookup_class_ex(type, lcname, class_name_len, ((!rt_ns_check && use_autoload) ? class_name : NULL_ZSTR), 0, &pce TSRMLS_CC)==FAILURE) {
                if (rt_ns_check) {
                        /* Check if we have internal class with the same name */
-                       zstr php_name;
+                       zstr php_name = NULL_ZSTR;
+                       uint php_name_len;
                        
                        if (type == IS_UNICODE) {
                                php_name.u = u_memrchr(lcname.u, ':', class_name_len);
                                if (php_name.u) {
                                        php_name.u++;
-                                       if (zend_u_lookup_class_ex(type, php_name, class_name_len-(php_name.u-lcname.u), 0, do_normalize, &pce TSRMLS_CC)==SUCCESS &&
-                                           (*pce)->type == ZEND_INTERNAL_CLASS) {
-                                               if (lcname.v != class_name.v) {
-                                                       efree(lcname.v);
-                                               }
-                                               return *pce;
-                                       }
+                                       php_name_len = class_name_len-(php_name.u-lcname.u);
                                }
                        } else {
                                php_name.s = zend_memrchr(lcname.s, ':', class_name_len);
                                if (php_name.s) {
                                        php_name.s++;
-                                       if (zend_u_lookup_class_ex(type, php_name, class_name_len-(php_name.s-lcname.s), 0, do_normalize, &pce TSRMLS_CC)==SUCCESS &&
-                                           (*pce)->type == ZEND_INTERNAL_CLASS) {
-                                               if (lcname.v != class_name.v) {
-                                                       efree(lcname.v);
-                                               }
-                                               return *pce;
-                                       }
+                                       php_name_len = class_name_len-(php_name.s-lcname.s);
                                }
                        }
+                       if (php_name.v &&
+                           zend_u_hash_find(EG(class_table), type, php_name, php_name_len+1, (void **) &pce) == SUCCESS &&
+                           (*pce)->type == ZEND_INTERNAL_CLASS) {
+                               if (lcname.v != class_name.v) {
+                                       efree(lcname.v);
+                               }
+                               return *pce;
+                       }
                }
                if (use_autoload) {
+                       if (rt_ns_check &&
+                           zend_u_lookup_class_ex(type, lcname, class_name_len, class_name, 0, &pce TSRMLS_CC)==SUCCESS) {
+                               if (lcname.v != class_name.v) {
+                                       efree(lcname.v);
+                               }
+                               return *pce;
+                       }
                        if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
                                zend_error(E_ERROR, "Interface '%R' not found", type, class_name);
                        } else {
index cf8486bd9aef9a5b5803fe631ab142a55b7eccaf..043e9983eadb20b5915a2de152eb4da32ed31f53 100644 (file)
@@ -2705,8 +2705,6 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
 ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED|CONST, CONST)
 {
        zend_op *opline = EX(opline);
-       zend_class_entry *ce = NULL;
-       zval **value;
 
        if (OP1_TYPE == IS_UNUSED) {
                if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
@@ -2717,50 +2715,58 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|UNUSED|CONST, CONST)
                        zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
                }
                ZEND_VM_NEXT_OPCODE();
-       } else if (OP1_TYPE == IS_CONST) {
-               zend_op *op_data = opline + 1;
-               zend_constant *c;
+       } else {
+               zend_class_entry *ce;
+               zval **value;
+       
+               if (OP1_TYPE == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
 
-               ZEND_VM_INC_OPCODE();
+                       ZEND_VM_INC_OPCODE();
 
-               /* try a constant in namespace */
-               if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
-                       EX_T(opline->result.u.var).tmp_var = c->value;
-                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-                       ZEND_VM_NEXT_OPCODE();
-               } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
-                       if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
-                               zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
-                               EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                       /* try a constant in namespace */
+                       if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
                                zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                                       EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               }
+                               ZEND_VM_NEXT_OPCODE();
                        }
-                       ZEND_VM_NEXT_OPCODE();
+       
+                       /* no constant found. try a constant in class */                
+                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);          
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
                }
 
-               /* no constant found. try a constant in class */                
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);          
-               if (!ce) {
+               if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               zend_class_entry *old_scope = EG(scope);
+
+                               EG(scope) = ce;
+                               zval_update_constant(value, (void *) 1 TSRMLS_CC);
+                               EG(scope) = old_scope;
+                       }
+                       EX_T(opline->result.u.var).tmp_var = **value;
+                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+               } else {
                        zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
                }
-       } else {
-               ce = EX_T(opline->op1.u.var).class_entry;
-       }
-
-       if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
-               zend_class_entry *old_scope = EG(scope);
 
-               EG(scope) = ce;
-               zval_update_constant(value, (void *) 1 TSRMLS_CC);
-               EG(scope) = old_scope;
-               EX_T(opline->result.u.var).tmp_var = **value;
-               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-       } else {
-               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+               ZEND_VM_NEXT_OPCODE();
        }
-
-       ZEND_VM_NEXT_OPCODE();
 }
 
 ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV)
index 41d6275748b61f275d3eda0d63e583d6dfe6bb01..1756076a38b6446e3a38016cf64c88247a5b9998 100644 (file)
@@ -2656,8 +2656,6 @@ static int ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
-       zend_class_entry *ce = NULL;
-       zval **value;
 
        if (IS_CONST == IS_UNUSED) {
                if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
@@ -2668,50 +2666,58 @@ static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
                        zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
                }
                ZEND_VM_NEXT_OPCODE();
-       } else if (IS_CONST == IS_CONST) {
-               zend_op *op_data = opline + 1;
-               zend_constant *c;
+       } else {
+               zend_class_entry *ce;
+               zval **value;
 
-               ZEND_VM_INC_OPCODE();
+               if (IS_CONST == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
 
-               /* try a constant in namespace */
-               if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
-                       EX_T(opline->result.u.var).tmp_var = c->value;
-                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-                       ZEND_VM_NEXT_OPCODE();
-               } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
-                       if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
-                               zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
-                               EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                       ZEND_VM_INC_OPCODE();
+
+                       /* try a constant in namespace */
+                       if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
                                zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                                       EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               }
+                               ZEND_VM_NEXT_OPCODE();
                        }
-                       ZEND_VM_NEXT_OPCODE();
+
+                       /* no constant found. try a constant in class */
+                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
                }
 
-               /* no constant found. try a constant in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
-               if (!ce) {
+               if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               zend_class_entry *old_scope = EG(scope);
+
+                               EG(scope) = ce;
+                               zval_update_constant(value, (void *) 1 TSRMLS_CC);
+                               EG(scope) = old_scope;
+                       }
+                       EX_T(opline->result.u.var).tmp_var = **value;
+                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+               } else {
                        zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
                }
-       } else {
-               ce = EX_T(opline->op1.u.var).class_entry;
-       }
-
-       if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
-               zend_class_entry *old_scope = EG(scope);
 
-               EG(scope) = ce;
-               zval_update_constant(value, (void *) 1 TSRMLS_CC);
-               EG(scope) = old_scope;
-               EX_T(opline->result.u.var).tmp_var = **value;
-               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-       } else {
-               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+               ZEND_VM_NEXT_OPCODE();
        }
-
-       ZEND_VM_NEXT_OPCODE();
 }
 
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -10123,8 +10129,6 @@ static int ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 static int ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
-       zend_class_entry *ce = NULL;
-       zval **value;
 
        if (IS_VAR == IS_UNUSED) {
                if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
@@ -10135,50 +10139,58 @@ static int ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
                }
                ZEND_VM_NEXT_OPCODE();
-       } else if (IS_VAR == IS_CONST) {
-               zend_op *op_data = opline + 1;
-               zend_constant *c;
+       } else {
+               zend_class_entry *ce;
+               zval **value;
 
-               ZEND_VM_INC_OPCODE();
+               if (IS_VAR == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
 
-               /* try a constant in namespace */
-               if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
-                       EX_T(opline->result.u.var).tmp_var = c->value;
-                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-                       ZEND_VM_NEXT_OPCODE();
-               } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
-                       if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
-                               zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
-                               EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                       ZEND_VM_INC_OPCODE();
+
+                       /* try a constant in namespace */
+                       if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
                                zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                                       EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               }
+                               ZEND_VM_NEXT_OPCODE();
                        }
-                       ZEND_VM_NEXT_OPCODE();
+
+                       /* no constant found. try a constant in class */
+                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
                }
 
-               /* no constant found. try a constant in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
-               if (!ce) {
+               if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               zend_class_entry *old_scope = EG(scope);
+
+                               EG(scope) = ce;
+                               zval_update_constant(value, (void *) 1 TSRMLS_CC);
+                               EG(scope) = old_scope;
+                       }
+                       EX_T(opline->result.u.var).tmp_var = **value;
+                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+               } else {
                        zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
                }
-       } else {
-               ce = EX_T(opline->op1.u.var).class_entry;
-       }
 
-       if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
-               zend_class_entry *old_scope = EG(scope);
-
-               EG(scope) = ce;
-               zval_update_constant(value, (void *) 1 TSRMLS_CC);
-               EG(scope) = old_scope;
-               EX_T(opline->result.u.var).tmp_var = **value;
-               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-       } else {
-               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+               ZEND_VM_NEXT_OPCODE();
        }
-
-       ZEND_VM_NEXT_OPCODE();
 }
 
 static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -16853,8 +16865,6 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
 static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
-       zend_class_entry *ce = NULL;
-       zval **value;
 
        if (IS_UNUSED == IS_UNUSED) {
                if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
@@ -16865,50 +16875,58 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
                        zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
                }
                ZEND_VM_NEXT_OPCODE();
-       } else if (IS_UNUSED == IS_CONST) {
-               zend_op *op_data = opline + 1;
-               zend_constant *c;
+       } else {
+               zend_class_entry *ce;
+               zval **value;
 
-               ZEND_VM_INC_OPCODE();
+               if (IS_UNUSED == IS_CONST) {
+                       zend_op *op_data = opline + 1;
+                       zend_constant *c;
 
-               /* try a constant in namespace */
-               if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
-                       EX_T(opline->result.u.var).tmp_var = c->value;
-                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-                       ZEND_VM_NEXT_OPCODE();
-               } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
-                       if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
-                               zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
-                                       Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
-                               EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                       ZEND_VM_INC_OPCODE();
+
+                       /* try a constant in namespace */
+                       if (zend_u_hash_quick_find(EG(zend_constants), Z_TYPE(op_data->op1.u.constant), Z_UNIVAL(op_data->op1.u.constant), Z_UNILEN(op_data->op1.u.constant)+1, op_data->extended_value, (void **) &c)==SUCCESS) {
+                               EX_T(opline->result.u.var).tmp_var = c->value;
                                zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if ((opline->extended_value & IS_CONSTANT_RT_NS_CHECK) != 0) {
+                               if (!zend_u_get_constant(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+                                       zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+                                               Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                                       EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
+                                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+                               }
+                               ZEND_VM_NEXT_OPCODE();
                        }
-                       ZEND_VM_NEXT_OPCODE();
+
+                       /* no constant found. try a constant in class */
+                       ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
+                       if (!ce) {
+                               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+                       }
+               } else {
+                       ce = EX_T(opline->op1.u.var).class_entry;
                }
 
-               /* no constant found. try a constant in class */
-               ce = zend_u_fetch_class(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), opline->extended_value TSRMLS_CC);
-               if (!ce) {
+               if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
+                       if (Z_TYPE_PP(value) == IS_CONSTANT_ARRAY ||
+                           Z_TYPE_PP(value) == IS_CONSTANT) {
+                               zend_class_entry *old_scope = EG(scope);
+
+                               EG(scope) = ce;
+                               zval_update_constant(value, (void *) 1 TSRMLS_CC);
+                               EG(scope) = old_scope;
+                       }
+                       EX_T(opline->result.u.var).tmp_var = **value;
+                       zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
+               } else {
                        zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
                }
-       } else {
-               ce = EX_T(opline->op1.u.var).class_entry;
-       }
-
-       if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
-               zend_class_entry *old_scope = EG(scope);
 
-               EG(scope) = ce;
-               zval_update_constant(value, (void *) 1 TSRMLS_CC);
-               EG(scope) = old_scope;
-               EX_T(opline->result.u.var).tmp_var = **value;
-               zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
-       } else {
-               zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
+               ZEND_VM_NEXT_OPCODE();
        }
-
-       ZEND_VM_NEXT_OPCODE();
 }
 
 static int ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)