]> granicus.if.org Git - php/commitdiff
Refactored IS_INDIRECT usage for CV and object properties to support HashTable resizing
authorDmitry Stogov <dmitry@zend.com>
Wed, 26 Mar 2014 14:07:31 +0000 (18:07 +0400)
committerDmitry Stogov <dmitry@zend.com>
Wed, 26 Mar 2014 14:07:31 +0000 (18:07 +0400)
25 files changed:
Zend/zend.c
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_gc.c
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_object_handlers.c
Zend/zend_objects.c
Zend/zend_variables.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/reflection/php_reflection.c
ext/spl/spl_array.c
ext/standard/array.c
ext/standard/basic_functions.c
ext/standard/http.c
ext/standard/http_fopen_wrapper.c
ext/standard/var.c
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re
main/main.c
main/php_variables.c

index a494c97dc94b49cafd6adbe17a75ea3b5975b99c..8b58d4b8b0a37fa49ef24f150b646376146dddba 100644 (file)
@@ -144,6 +144,13 @@ static void print_hash(zend_write_func_t write_func, HashTable *ht, int indent,
        indent += PRINT_ZVAL_INDENT;
        zend_hash_internal_pointer_reset_ex(ht, &iterator);
        while ((tmp = zend_hash_get_current_data_ex(ht, &iterator)) != NULL) {
+               if (Z_TYPE_P(tmp) == IS_INDIRECT) {
+                       tmp = Z_INDIRECT_P(tmp);
+                       if (Z_TYPE_P(tmp) == IS_UNDEF) {
+                               zend_hash_move_forward_ex(ht, &iterator);
+                               continue;
+                       }
+               }
                for (i = 0; i < indent; i++) {
                        ZEND_PUTS_EX(" ");
                }
index e9d30811db7a42c573f7795187aa784424b9f857..c0bb644ee20a1df7deb2241f8ac28c4b0c84f00d 100644 (file)
@@ -1230,6 +1230,70 @@ ZEND_API void object_properties_init(zend_object *object, zend_class_entry *clas
 }
 /* }}} */
 
+ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
+{
+       object->properties = properties;
+       if (object->ce->default_properties_count) {
+               HashPosition pos;
+           zval *prop, tmp;
+       zend_string *key;
+           ulong num_key;
+       zend_property_info *property_info;
+
+               for (zend_hash_internal_pointer_reset_ex(properties, &pos);
+                    (prop = zend_hash_get_current_data_ex(properties, &pos)) != NULL &&
+                zend_hash_get_current_key_ex(properties, &key, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
+                    zend_hash_move_forward_ex(properties, &pos)) {
+
+                   ZVAL_STR(&tmp, key);
+                       property_info = zend_get_property_info(object->ce, &tmp, 1 TSRMLS_CC);
+                       if (property_info &&
+                           (property_info->flags & ZEND_ACC_STATIC) == 0 &&
+                           property_info->offset >= 0) {
+                               ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
+                               ZVAL_INDIRECT(prop, &object->properties_table[property_info->offset]);
+                       }
+               }               
+       }
+}
+/* }}} */
+
+ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
+{
+       HashPosition pos;
+    zval *prop, tmp;
+       zend_string *key;
+    ulong num_key;
+       zend_property_info *property_info;
+
+       for (zend_hash_internal_pointer_reset_ex(properties, &pos);
+            (prop = zend_hash_get_current_data_ex(properties, &pos)) != NULL &&
+        zend_hash_get_current_key_ex(properties, &key, &num_key, 0, &pos) == HASH_KEY_IS_STRING;
+            zend_hash_move_forward_ex(properties, &pos)) {
+
+           ZVAL_STR(&tmp, key);
+               property_info = zend_get_property_info(object->ce, &tmp, 1 TSRMLS_CC);
+               if (property_info &&
+                   (property_info->flags & ZEND_ACC_STATIC) == 0 &&
+                   property_info->offset >= 0) {
+                   zval_ptr_dtor(&object->properties_table[property_info->offset]);
+                       ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
+                       zval_add_ref(&object->properties_table[property_info->offset]);
+                       if (object->properties) {
+                               ZVAL_INDIRECT(&tmp, &object->properties_table[property_info->offset]);
+                               prop = zend_hash_update(object->properties, key, &tmp);
+                       }
+               } else {
+                       if (!object->properties) {
+                               rebuild_object_properties(object);
+                       }
+                       prop = zend_hash_update(object->properties, key, prop);
+                       zval_add_ref(prop);
+               }
+       }               
+}
+/* }}} */
+
 /* This function requires 'properties' to contain all props declared in the
  * class and all props being public. If only a subset is given or the class
  * has protected members then you need to merge the properties separately by
@@ -1248,8 +1312,7 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
        if (class_type->create_object == NULL) {
                ZVAL_OBJ(arg, zend_objects_new(class_type TSRMLS_CC));
                if (properties) {
-                       Z_OBJ_P(arg)->properties = properties;
-//???                  Z_OBJ_P(arg)->properties_table = NULL;
+                       object_properties_init_ex(Z_OBJ_P(arg), properties);
                } else {
                        object_properties_init(Z_OBJ_P(arg), class_type);
                }
index d759803345e38c6060b6c2c81df0705c47aaef7c..c05e430e4c59402d74ba78fe8a379918e191f7a7 100644 (file)
@@ -366,6 +366,8 @@ ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC);
 ZEND_API int _object_init_ex(zval *arg, zend_class_entry *ce ZEND_FILE_LINE_DC TSRMLS_DC);
 ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *ce, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC);
 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type);
+ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties);
+ZEND_API void object_properties_load(zend_object *object, HashTable *properties);
 
 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC);
 
@@ -515,13 +517,12 @@ ZEND_API int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci
 
 ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...);
 
-ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, zend_string *name TSRMLS_DC);
-
 ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC);
 
-ZEND_API void zend_reset_all_cv(zend_array *symbol_table TSRMLS_DC);
-
 ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
+ZEND_API void zend_attach_symbol_table(TSRMLS_D);
+ZEND_API void zend_detach_symbol_table(TSRMLS_D);
+ZEND_API int zend_set_local_var(const char *name, int len, zval *value, int force TSRMLS_DC);
 
 ZEND_API zend_string *zend_find_alias_name(zend_class_entry *ce, zend_string *name);
 ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_function *f);
index 5691fd0b6910276f8577113348cbf4ccd8a72abb..06c4774873d18a243cc001180f3ee732e258cf7c 100644 (file)
@@ -593,9 +593,18 @@ ZEND_FUNCTION(each)
                zend_error(E_WARNING,"Variable passed to each() is not an array or object");
                return;
        }
-       entry = zend_hash_get_current_data(target_hash);
-       if (!entry) {
-               RETURN_FALSE;
+       while (1) {
+               entry = zend_hash_get_current_data(target_hash);
+               if (!entry) {
+                       RETURN_FALSE;
+               } else if (Z_TYPE_P(entry) == IS_INDIRECT) {
+                       entry = Z_INDIRECT_P(entry);
+                       if (Z_TYPE_P(entry) == IS_UNDEF) {
+                               zend_hash_move_forward(target_hash);
+                               continue;
+                       }
+               }
+               break;
        }
        array_init(return_value);
 
@@ -999,6 +1008,13 @@ ZEND_FUNCTION(get_object_vars)
        zend_hash_internal_pointer_reset_ex(properties, &pos);
 
        while ((value = zend_hash_get_current_data_ex(properties, &pos)) != NULL) {
+               if (Z_TYPE_P(value) == IS_INDIRECT) {
+                       value = Z_INDIRECT_P(value);
+                       if (Z_TYPE_P(value) == IS_UNDEF) {
+                               zend_hash_move_forward_ex(properties, &pos);
+                               continue;
+                       }
+               }
                if (zend_hash_get_current_key_ex(properties, &key, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
                        if (zend_check_property_access(zobj, key TSRMLS_CC) == SUCCESS) {
                                zend_unmangle_property_name_ex(key->val, key->len, &class_name, &prop_name, (int*) &prop_len);
index bc498fee0a4ff04e26c39e06f7327b5bbaae893a..51f58cf2cd5741a935c61cccd44633804b2ded5a 100644 (file)
@@ -206,52 +206,31 @@ static zend_always_inline zval *_get_zval_ptr_var_deref(zend_uint var, const zen
 
 static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, zend_uint var, int type TSRMLS_DC)
 {
-       zend_string *cv = CV_DEF_OF(var);
-       zval *ret = NULL;
-
-       if (EG(active_symbol_table)) {
-               ret = zend_hash_find(&EG(active_symbol_table)->ht, cv);
-               if (ret) {
-                       ZVAL_INDIRECT(ptr, ret);
-                       return ret;
-               }
-       }
+       zend_string *cv;
 
        switch (type) {
                case BP_VAR_R:
                case BP_VAR_UNSET:
+                       cv = CV_DEF_OF(var);
                        zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
                        /* break missing intentionally */
                case BP_VAR_IS:
-                       return &EG(uninitialized_zval);
+                       ptr = &EG(uninitialized_zval);
+                       break;
                case BP_VAR_RW:
+                       cv = CV_DEF_OF(var);
                        zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
                        /* break missing intentionally */
                case BP_VAR_W:
-                       if (EG(active_symbol_table)) {
-                               ret = zend_hash_update(&EG(active_symbol_table)->ht, cv, ret);
-                               ZVAL_INDIRECT(ptr, ret);
-                       } else {
-                               ZVAL_NULL(ptr);
-                               ret = ptr;
-                       }
+                       ZVAL_NULL(ptr);
                        break;
        }
-       return ret;
+       return ptr;
 }
 
 static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint var TSRMLS_DC)
 {
        zend_string *cv = CV_DEF_OF(var);
-       zval *ret = NULL;
-
-       if (EG(active_symbol_table)) {
-               ret = zend_hash_find(&EG(active_symbol_table)->ht, cv);
-               if (ret) {
-                       ZVAL_INDIRECT(ptr, ret);
-                       return ret;
-               }
-       }
 
        zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
        return &EG(uninitialized_zval);
@@ -260,15 +239,6 @@ static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, zend_uint
 static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_uint var TSRMLS_DC)
 {
        zend_string *cv = CV_DEF_OF(var);
-       zval *ret;
-
-       if (EG(active_symbol_table)) {
-               ret = zend_hash_find(&EG(active_symbol_table)->ht, cv);
-               if (ret) {
-                       ZVAL_INDIRECT(ptr, ret);
-                       return ret;
-               }
-       }
 
        zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
        return &EG(uninitialized_zval);
@@ -276,60 +246,22 @@ static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, zend_
 
 static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_IS(zval *ptr, zend_uint var TSRMLS_DC)
 {
-       zend_string *cv = CV_DEF_OF(var);
-       zval *ret;
-
-       if (EG(active_symbol_table)) {
-               ret = zend_hash_find(&EG(active_symbol_table)->ht, cv);
-               if (ret) {
-                       ZVAL_INDIRECT(ptr, ret);
-                       return ret;
-               }
-       }
-
        return &EG(uninitialized_zval);
 }
 
 static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, zend_uint var TSRMLS_DC)
 {
        zend_string *cv = CV_DEF_OF(var);
-       zval *ret;
 
-       if (EG(active_symbol_table)) {
-               ret = zend_hash_find(&EG(active_symbol_table)->ht, cv);
-               if (ret) {
-                       ZVAL_INDIRECT(ptr, ret);
-                       return ret;
-               }
-               ret = zend_hash_update(&EG(active_symbol_table)->ht, cv, &EG(uninitialized_zval));
-               ZVAL_INDIRECT(ptr, ret);
-               zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
-               return ret;
-       } else {
-               ZVAL_NULL(ptr);
-               zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
-               return ptr;
-       }
+       ZVAL_NULL(ptr);
+       zend_error(E_NOTICE, "Undefined variable: %s", cv->val);
+       return ptr;
 }
 
 static zend_never_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, zend_uint var TSRMLS_DC)
 {
-       zend_string *cv = CV_DEF_OF(var);
-       zval *ret;
-
-       if (EG(active_symbol_table)) {
-               ret = zend_hash_find(&EG(active_symbol_table)->ht, cv);
-               if (ret) {
-                       ZVAL_INDIRECT(ptr, ret);
-                       return ret;
-               }
-               ret = zend_hash_update(&EG(active_symbol_table)->ht, cv, &EG(uninitialized_zval));
-               ZVAL_INDIRECT(ptr, ret);
-               return ret;
-       } else {
-               ZVAL_NULL(ptr);
-               return ptr;
-       }
+       ZVAL_NULL(ptr);
+       return ptr;
 }
 
 static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_DC)
@@ -338,8 +270,6 @@ static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup(ret, var, type TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        return ret;
 }
@@ -350,8 +280,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref(zend_uint var, int type T
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup(ret, var, type TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) {
                ret = Z_REFVAL_P(ret);
@@ -365,8 +293,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_dat
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_R(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        return ret;
 }
@@ -377,8 +303,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execu
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_R(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) {
                ret = Z_REFVAL_P(ret);
@@ -392,8 +316,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        return ret;
 }
@@ -404,8 +326,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_e
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) {
                ret = Z_REFVAL_P(ret);
@@ -419,8 +339,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_da
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_IS(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        return ret;
 }
@@ -431,8 +349,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_exec
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_IS(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) {
                ret = Z_REFVAL_P(ret);
@@ -446,8 +362,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_da
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_RW(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        return ret;
 }
@@ -458,8 +372,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_exec
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_RW(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) {
                ret = Z_REFVAL_P(ret);
@@ -473,8 +385,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_dat
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_W(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        return ret;
 }
@@ -485,8 +395,6 @@ static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execu
 
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
                return _get_zval_cv_lookup_BP_VAR_W(ret, var TSRMLS_CC);
-       } else if (UNEXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
-               ret = Z_INDIRECT_P(ret);
        }
        if (UNEXPECTED(Z_TYPE_P(ret) == IS_REFERENCE)) {
                ret = Z_REFVAL_P(ret);
@@ -774,10 +682,6 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
                                }
                                Z_ADDREF_P(object);
                                zend_error(E_WARNING, "Creating default object from empty value");
-//???
-                               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                                       object = Z_INDIRECT_P(object);
-                               }
                                if (Z_REFCOUNT_P(object) == 1) {
                                        /* object was removed by error handler, nothing to assign to */
                                        zval_ptr_dtor(object);
@@ -790,10 +694,6 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p
                                Z_DELREF_P(object);
                        } else {
                                zend_error(E_WARNING, "Creating default object from empty value");
-//???
-                               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                                       object = Z_INDIRECT_P(object);
-                               }
                        }
                        zval_dtor(object);
                        object_init(object);
@@ -1098,7 +998,29 @@ static inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval
                        }
 fetch_string_dim:
                        retval = zend_hash_find(ht, offset_key);
-                       if (retval == NULL) {
+// ??? support for $GLOBALS[...]
+                       if (retval) {
+                               if (Z_TYPE_P(retval) == IS_INDIRECT) {
+                                       retval = Z_INDIRECT_P(retval);
+                                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                                               switch (type) {
+                                                       case BP_VAR_R:
+                                                               zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
+                                                               /* break missing intentionally */
+                                                       case BP_VAR_UNSET:
+                                                       case BP_VAR_IS:
+                                                               retval = &EG(uninitialized_zval);
+                                                               break;
+                                                       case BP_VAR_RW:
+                                                               zend_error(E_NOTICE,"Undefined index: %s", offset_key->val);
+                                                               /* break missing intentionally */
+                                                       case BP_VAR_W:
+                                                               ZVAL_NULL(retval);
+                                                               break;
+                                               }
+                                       }
+                               }
+                       } else { 
                                switch (type) {
                                        case BP_VAR_R:
                                                zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
@@ -1247,10 +1169,6 @@ convert_to_array:
                                        convert_to_long(&tmp);
                                        dim = &tmp;
                                }
-//??? container may became IS_INDIRECT because of symtable initialization in zend_error
-                               if (Z_TYPE_P(container) == IS_INDIRECT) {
-                                       container = Z_INDIRECT_P(container);
-                               }
                                ZVAL_STR_OFFSET(result, container, Z_LVAL_P(dim));
                                if (!IS_INTERNED(Z_STR_P(container))) STR_ADDREF(Z_STR_P(container));
                                return;
@@ -1719,16 +1637,12 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
                op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
        }
 
+       if (EG(active_symbol_table)) {
+               zend_attach_symbol_table(TSRMLS_C);
+       }
+
        if (op_array->this_var != -1 && Z_TYPE(EG(This)) != IS_UNDEF) {
-               if (!EG(active_symbol_table)) {
-                       ZVAL_COPY(EX_VAR_NUM(op_array->this_var), &EG(This));
-               } else {
-                       ZVAL_COPY(EX_VAR_NUM(op_array->this_var), &EG(This));
-                       zval *zv = zend_hash_str_add(&EG(active_symbol_table)->ht, "this", sizeof("this")-1, EX_VAR(op_array->this_var));
-                       if (zv) {
-                               ZVAL_INDIRECT(EX_VAR_NUM(op_array->this_var), zv);
-                       }
-               }
+               ZVAL_COPY(EX_VAR_NUM(op_array->this_var), &EG(This));
        }
 
        EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
index a90dade13981677e4ef1221e69148cbfe47e3ba9..0980517935664f53aadb525824929ea3ef51c792 100644 (file)
@@ -202,6 +202,9 @@ void init_executor(TSRMLS_D) /* {{{ */
 
 static int zval_call_destructor(zval *zv TSRMLS_DC) /* {{{ */
 {
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+       }
        if (Z_TYPE_P(zv) == IS_OBJECT && Z_REFCOUNT_P(zv) == 1) {
                return ZEND_HASH_APPLY_REMOVE;
        } else {
@@ -210,8 +213,22 @@ static int zval_call_destructor(zval *zv TSRMLS_DC) /* {{{ */
 }
 /* }}} */
 
+static int zend_unclean_zval_ptr_dtor(zval *zv) /* {{{ */
+{
+       TSRMLS_FETCH();
+
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+       }
+       i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC TSRMLS_CC);
+}
+/* }}} */
+
 void shutdown_destructors(TSRMLS_D) /* {{{ */
 {
+       if (CG(unclean_shutdown)) {
+               EG(symbol_table).ht.pDestructor = zend_unclean_zval_ptr_dtor;
+       }
        zend_try {
                int symbols;
                do {
@@ -246,6 +263,10 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
                }
 */
                zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC);
+
+               if (CG(unclean_shutdown)) {
+                       EG(symbol_table).ht.pDestructor = zend_unclean_zval_ptr_dtor;
+               }
                zend_hash_graceful_reverse_destroy(&EG(symbol_table).ht);
        } zend_end_try();
 
@@ -1638,65 +1659,9 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC) /* {{{ */
 }
 /* }}} */
 
-ZEND_API void zend_reset_all_cv(zend_array *symbol_table TSRMLS_DC) /* {{{ */
-{
-       zend_execute_data *ex;
-       int i;
-
-       for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
-               if (ex->op_array && ex->symbol_table == symbol_table) {
-                       for (i = 0; i < ex->op_array->last_var; i++) {
-                               ZVAL_UNDEF(EX_VAR_NUM_2(ex, i));
-                       }
-               }
-       }
-}
-/* }}} */
-
-ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, zend_string *name TSRMLS_DC) /* {{{ */
-{
-       if (zend_hash_del(ht, name) == SUCCESS) {
-               while (ex && &ex->symbol_table->ht == ht) {
-                       int i;
-
-                       if (ex->op_array) {
-                               for (i = 0; i < ex->op_array->last_var; i++) {
-                                       if (ex->op_array->vars[i]->h == name->h &&
-                                               ex->op_array->vars[i]->len == name->len &&
-                                               !memcmp(ex->op_array->vars[i]->val, name->val, name->len)) {
-                                               ZVAL_UNDEF(EX_VAR_NUM_2(ex, i));
-                                               break;
-                                       }
-                               }
-                       }
-                       ex = ex->prev_execute_data;
-               }
-       }
-}
-/* }}} */
-
 ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC) /* {{{ */
 {
-       zend_execute_data *ex;
-
-       if (zend_hash_del(&EG(symbol_table).ht, name) == SUCCESS) {
-               for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
-                       if (ex->op_array && ex->symbol_table == &EG(symbol_table)) {
-                               int i;
-                               for (i = 0; i < ex->op_array->last_var; i++) {
-                                       if (ex->op_array->vars[i]->h == name->h &&
-                                               ex->op_array->vars[i]->len == name->len &&
-                                               !memcmp(ex->op_array->vars[i]->val, name->val, name->len)
-                                       ) {
-                                               ZVAL_UNDEF(EX_VAR_NUM_2(ex, i));
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               return SUCCESS;
-       }
-       return FAILURE;
+    return zend_hash_del_ind(&EG(symbol_table).ht, name);
 }
 /* }}} */
 
@@ -1736,18 +1701,97 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
                            ZVAL_COPY_VALUE(EX_VAR_NUM_2(ex, ex->op_array->this_var), &EG(This));
                        }
                        for (i = 0; i < ex->op_array->last_var; i++) {
-                               if (Z_TYPE_P(EX_VAR_NUM_2(ex, i)) != IS_UNDEF) {
-                                       zval *zv = zend_hash_update(&EG(active_symbol_table)->ht,
-                                               ex->op_array->vars[i],
-                                               EX_VAR_NUM_2(ex, i));
-                                       ZVAL_INDIRECT(EX_VAR_NUM_2(ex, i), zv);
+                               zval zv;
+                                       
+                               ZVAL_INDIRECT(&zv, EX_VAR_NUM_2(ex, i));
+                               zend_hash_update(&EG(active_symbol_table)->ht,
+                                       ex->op_array->vars[i], &zv);
+                       }
+               }
+       }
+}
+/* }}} */
+
+ZEND_API void zend_attach_symbol_table(TSRMLS_D) /* {{{ */
+{
+       int i;
+       zend_execute_data *execute_data = EG(current_execute_data);
+       zend_op_array *op_array = execute_data->op_array;
+       HashTable *ht = &EG(active_symbol_table)->ht;
+       
+       /* copy real values from symbol table into CV slots and create
+          INDIRECT references to CV in symbol table  */
+       for (i = 0; i < op_array->last_var; i++) {
+               zval *zv = zend_hash_find(ht, op_array->vars[i]);
+
+               if (zv) {
+                       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+                               zval *val = Z_INDIRECT_P(zv);
+                               if (Z_TYPE_P(val) == IS_UNDEF) {
+                                       ZVAL_UNDEF(EX_VAR_NUM(i));
+                               } else {
+                                       ZVAL_COPY_VALUE(EX_VAR_NUM(i), val);
                                }
+                       } else {
+                               ZVAL_COPY_VALUE(EX_VAR_NUM(i), zv);
                        }
+               } else {
+                       ZVAL_UNDEF(EX_VAR_NUM(i));
+                       zv = zend_hash_update(ht, op_array->vars[i], EX_VAR_NUM(i));
                }
+               ZVAL_INDIRECT(zv, EX_VAR_NUM(i));
        }
 }
 /* }}} */
 
+ZEND_API void zend_detach_symbol_table(TSRMLS_D) /* {{{ */
+{
+       int i;
+       zend_execute_data *execute_data = EG(current_execute_data);
+       zend_op_array *op_array = execute_data->op_array;
+       HashTable *ht = &EG(active_symbol_table)->ht;
+       
+       /* copy real values from CV slots into symbol table */
+       for (i = 0; i < op_array->last_var; i++) {
+               zend_hash_update(ht, op_array->vars[i], EX_VAR_NUM(i));
+               ZVAL_UNDEF(EX_VAR_NUM(i));
+       }
+}
+/* }}} */
+
+ZEND_API int zend_set_local_var(const char *name, int len, zval *value, int force TSRMLS_DC) /* {{{ */
+{
+       if (!EG(active_symbol_table)) {
+               int i;
+               zend_execute_data *execute_data = EG(current_execute_data);
+               zend_op_array *op_array = execute_data->op_array;
+               zend_ulong h = zend_hash_func(name, len);
+
+               if (op_array) {
+                       for (i = 0; i < op_array->last_var; i++) {
+                               if (op_array->vars[i]->h == h &&
+                                   op_array->vars[i]->len == len &&
+                                   memcmp(op_array->vars[i]->val, name, len) == 0) {
+                                       ZVAL_COPY_VALUE(EX_VAR_NUM(i), value);
+                                       return SUCCESS;
+                               }
+                       }
+               }
+               if (force) {
+                       zend_rebuild_symbol_table(TSRMLS_C);
+                       if (EG(active_symbol_table)) {
+                               zend_hash_str_update(&EG(active_symbol_table)->ht, name, len, value);
+                       }
+               } else {
+                       return FAILURE;
+               }
+       } else {
+               return zend_hash_str_update_ind(&EG(active_symbol_table)->ht, name, len, value);
+       }
+       return SUCCESS;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4
index 54fd532fc7787d30ce3d72a61813a43ea1b9d02f..dca99c091133a0a58ca6858f783a4e0bccf922dc 100644 (file)
@@ -557,7 +557,7 @@ tail_call:
                        p = ht->arData + idx;
                        if (!Z_REFCOUNTED(p->val)) {
                                /* count non-refcounted for compatibilty ??? */
-                               if (Z_TYPE(p->val) != IS_UNDEF) {
+                               if (Z_TYPE(p->val) != IS_UNDEF && Z_TYPE(p->val) != IS_INDIRECT) {
                                        count++;
                                }
                                continue;
index be2b0c742b5bd4ee42ccaf7a60f49ed47ca283fc..3cfc62e7a144824f601324f980fa1af6edfe4741 100644 (file)
@@ -267,17 +267,23 @@ ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *p
        p = zend_hash_find_bucket(ht, key);
 
        if (p) {
+               zval *data;
+
                if (flag & HASH_ADD) {
                        return NULL;
                }
                ZEND_ASSERT(&p->val != pData);
+               data = &p->val;
+               if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
+                       data = Z_INDIRECT_P(data);
+               }
                HANDLE_BLOCK_INTERRUPTIONS();
                if (ht->pDestructor) {
-                       ht->pDestructor(&p->val);
+                       ht->pDestructor(data);
                }
-               ZVAL_COPY_VALUE(&p->val, pData);
+               ZVAL_COPY_VALUE(data, pData);
                HANDLE_UNBLOCK_INTERRUPTIONS();
-               return &p->val;
+               return data;
        }
        
        ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
@@ -588,6 +594,58 @@ ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
        return FAILURE;
 }
 
+ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key)
+{
+       ulong h;
+       uint nIndex;
+       uint idx;
+       Bucket *p;
+       Bucket *prev = NULL;
+#ifdef ZEND_SIGNALS
+       TSRMLS_FETCH();
+#endif
+
+       IS_CONSISTENT(ht);
+
+       if (ht->flags & HASH_FLAG_PACKED) {
+               return FAILURE;
+       }
+
+       h = STR_HASH_VAL(key);
+       nIndex = h & ht->nTableMask;
+
+       idx = ht->arHash[nIndex];
+       while (idx != INVALID_IDX) {
+               p = ht->arData + idx;
+               if ((p->key == key) ||
+                       (p->h == h &&
+                    p->key &&
+                    p->key->len == key->len &&
+                    memcmp(p->key->val, key->val, key->len) == 0)) {
+                       if (Z_TYPE(p->val) == IS_INDIRECT) {
+                               zval *data = Z_INDIRECT(p->val);
+
+                               if (Z_TYPE_P(data) == IS_UNDEF) {
+                                       return FAILURE;
+                               } else {
+                                       if (ht->pDestructor) {
+                                               ht->pDestructor(data);
+                                       }
+                                       ZVAL_UNDEF(data);
+                               }
+                       } else {
+                               HANDLE_BLOCK_INTERRUPTIONS();
+                               _zend_hash_del_el_ex(ht, idx, p, prev);
+                               HANDLE_UNBLOCK_INTERRUPTIONS();
+                       }
+                       return SUCCESS;
+               }
+               prev = p;
+               idx = p->val.u.next;
+       }
+       return FAILURE;
+}
+
 ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, int len)
 {
        ulong h;
@@ -604,6 +662,53 @@ ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, int len)
        h = zend_inline_hash_func(str, len);
        nIndex = h & ht->nTableMask;
 
+       idx = ht->arHash[nIndex];
+       while (idx != INVALID_IDX) {
+               p = ht->arData + idx;
+               if ((p->h == h) 
+                        && p->key
+                        && (p->key->len == len)
+                        && !memcmp(p->key->val, str, len)) {
+                       if (Z_TYPE(p->val) == IS_INDIRECT) {
+                               zval *data = Z_INDIRECT(p->val);
+
+                               if (Z_TYPE_P(data) == IS_UNDEF) {
+                                       return FAILURE;
+                               } else {
+                                       if (ht->pDestructor) {
+                                               ht->pDestructor(data);
+                                       }
+                                       ZVAL_UNDEF(data);
+                               }
+                       } else {
+                               HANDLE_BLOCK_INTERRUPTIONS();
+                               _zend_hash_del_el_ex(ht, idx, p, prev);
+                               HANDLE_UNBLOCK_INTERRUPTIONS();
+                       }
+                       return SUCCESS;
+               }
+               prev = p;
+               idx = p->val.u.next;
+       }
+       return FAILURE;
+}
+
+ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, int len)
+{
+       ulong h;
+       uint nIndex;
+       uint idx;
+       Bucket *p;
+       Bucket *prev = NULL;
+#ifdef ZEND_SIGNALS
+       TSRMLS_FETCH();
+#endif
+
+       IS_CONSISTENT(ht);
+
+       h = zend_inline_hash_func(str, len);
+       nIndex = h & ht->nTableMask;
+
        idx = ht->arHash[nIndex];
        while (idx != INVALID_IDX) {
                p = ht->arData + idx;
@@ -914,7 +1019,7 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun
 {
     uint idx;
        Bucket *p;
-       zval *new_entry;
+       zval *new_entry, *data;
        zend_bool setTargetPointer;
 
        IS_CONSISTENT(source);
@@ -928,10 +1033,18 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun
                if (setTargetPointer && source->nInternalPointer == idx) {
                        target->nInternalPointer = INVALID_IDX;
                }
+//???
+               data = &p->val;
+               if (Z_TYPE_P(data) == IS_INDIRECT) {
+                       data = Z_INDIRECT_P(data);
+                       if (Z_TYPE_P(data) == IS_UNDEF) {
+                               continue;
+                       }
+               }
                if (p->key) {
-                       new_entry = zend_hash_update(target, p->key, &p->val);
+                       new_entry = zend_hash_update(target, p->key, data);
                } else {
-                       new_entry = zend_hash_index_update(target, p->h, &p->val);
+                       new_entry = zend_hash_index_update(target, p->h, data);
                }
                if (pCopyConstructor) {
                        pCopyConstructor(new_entry);
@@ -1551,7 +1664,7 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
        uint idx1, idx2;
        Bucket *p1, *p2 = NULL;
        int result;
-       zval *pData2;
+       zval *pData1, *pData2;
 
        IS_CONSISTENT(ht1);
        IS_CONSISTENT(ht2);
@@ -1620,7 +1733,22 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
                                }
                        }
                }
-               result = compar(&p1->val, pData2 TSRMLS_CC);
+               pData1 = &p1->val;
+               if (Z_TYPE_P(pData1) == IS_INDIRECT) {
+                       pData1 = Z_INDIRECT_P(pData1);
+               }
+               if (Z_TYPE_P(pData2) == IS_INDIRECT) {
+                       pData2 = Z_INDIRECT_P(pData2);
+               }
+               if (Z_TYPE_P(pData1) == IS_UNDEF) {
+                       if (Z_TYPE_P(pData2) != IS_UNDEF) {
+                               return -1;
+                       }
+               } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
+                       return 1;
+               } else {
+                       result = compar(pData1, pData2 TSRMLS_CC);
+               }
                if (result != 0) {
                        HASH_UNPROTECT_RECURSION(ht1); 
                        HASH_UNPROTECT_RECURSION(ht2); 
index 2718356497f19946a4d6b419a1b3670da0d2a965..b9918304cdda4c88d8f788ce80a18df108cfa358 100644 (file)
 #define HASH_KEY_NON_EXISTENT 3
 #define HASH_KEY_NON_EXISTANT HASH_KEY_NON_EXISTENT /* Keeping old define (with typo) for backward compatibility */
 
-#define HASH_UPDATE            (1<<0)
-#define HASH_ADD                       (1<<1)
-#define HASH_NEXT_INSERT       (1<<2)
+#define HASH_UPDATE                    (1<<0)
+#define HASH_ADD                               (1<<1)
+#define HASH_NEXT_INSERT               (1<<2)
+#define HASH_UPDATE_INDIRECT   (1<<3)
 
 #define HASH_UPDATE_KEY_IF_NONE    0
 #define HASH_UPDATE_KEY_IF_BEFORE  1
@@ -74,12 +75,16 @@ ZEND_API void zend_hash_to_packed(HashTable *ht);
 ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, int flag ZEND_FILE_LINE_DC);
 #define zend_hash_update(ht, key, pData) \
                _zend_hash_add_or_update(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC)
+#define zend_hash_update_ind(ht, key, pData) \
+               _zend_hash_add_or_update(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC)
 #define zend_hash_add(ht, key, pData) \
                _zend_hash_add_or_update(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC)
 
 ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *key, int len, zval *pData, int flag ZEND_FILE_LINE_DC);
 #define zend_hash_str_update(ht, key, len, pData) \
                _zend_hash_str_add_or_update(ht, key, len, pData, HASH_UPDATE ZEND_FILE_LINE_CC)
+#define zend_hash_str_update_ind(ht, key, len, pData) \
+               _zend_hash_str_add_or_update(ht, key, len, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC)
 #define zend_hash_str_add(ht, key, len, pData) \
                _zend_hash_str_add_or_update(ht, key, len, pData, HASH_ADD ZEND_FILE_LINE_CC)
 
@@ -117,7 +122,9 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
 
 /* Deletes */
 ZEND_API int zend_hash_del(HashTable *ht, zend_string *key);
+ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key);
 ZEND_API int zend_hash_str_del(HashTable *ht, const char *key, int len);
+ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *key, int len);
 ZEND_API int zend_hash_index_del(HashTable *ht, ulong h);
 
 /* Data retreival */
@@ -244,6 +251,25 @@ END_EXTERN_C()
        ZEND_HANDLE_NUMERIC_EX(key, length, idx, return func);                                  \
 } while (0)
 
+
+static inline zval *zend_hash_find_ind(const HashTable *ht, zend_string *key)
+{
+       zval *zv;
+
+       zv = zend_hash_find(ht, key);
+       return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ? Z_INDIRECT_P(zv) : zv;
+}
+
+
+static inline zval *zend_hash_str_find_ind(const HashTable *ht, const char *str, int len)
+{
+       zval *zv;
+
+       zv = zend_hash_str_find(ht, str, len);
+       return (zv && Z_TYPE_P(zv) == IS_INDIRECT) ? Z_INDIRECT_P(zv) : zv;
+}
+
+
 static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData)
 {
        ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_update(ht, idx, pData));
@@ -251,6 +277,13 @@ static inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *
 }
 
 
+static inline zval *zend_symtable_update_ind(HashTable *ht, zend_string *key, zval *pData)
+{
+       ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_update(ht, idx, pData));
+       return zend_hash_update_ind(ht, key, pData);
+}
+
+
 static inline int zend_symtable_del(HashTable *ht, zend_string *key)
 {
        ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_del(ht, idx));
@@ -258,6 +291,13 @@ static inline int zend_symtable_del(HashTable *ht, zend_string *key)
 }
 
 
+static inline int zend_symtable_del_ind(HashTable *ht, zend_string *key)
+{
+       ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_del(ht, idx));
+       return zend_hash_del_ind(ht, key);
+}
+
+
 static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
 {
        ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_find(ht, idx));
@@ -265,12 +305,20 @@ static inline zval *zend_symtable_find(const HashTable *ht, zend_string *key)
 }
 
 
+static inline zval *zend_symtable_find_ind(const HashTable *ht, zend_string *key)
+{
+       ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_find(ht, idx));
+       return zend_hash_find_ind(ht, key);
+}
+
+
 static inline int zend_symtable_exists(HashTable *ht, zend_string *key)
 {
        ZEND_HANDLE_NUMERIC(key->val, key->len+1, zend_hash_index_exists(ht, idx));
        return zend_hash_exists(ht, key);
 }
 
+
 static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int len, zval *pData)
 {
        ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_update(ht, idx, pData));
@@ -278,6 +326,13 @@ static inline zval *zend_symtable_str_update(HashTable *ht, const char *str, int
 }
 
 
+static inline zval *zend_symtable_str_update_ind(HashTable *ht, const char *str, int len, zval *pData)
+{
+       ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_update(ht, idx, pData));
+       return zend_hash_str_update_ind(ht, str, len, pData);
+}
+
+
 static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len)
 {
        ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_del(ht, idx));
@@ -285,6 +340,13 @@ static inline int zend_symtable_str_del(HashTable *ht, const char *str, int len)
 }
 
 
+static inline int zend_symtable_str_del_ind(HashTable *ht, const char *str, int len)
+{
+       ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_del(ht, idx));
+       return zend_hash_str_del_ind(ht, str, len);
+}
+
+
 static inline zval *zend_symtable_str_find(HashTable *ht, const char *str, int len)
 {
        ZEND_HANDLE_NUMERIC(str, len+1, zend_hash_index_find(ht, idx));
index 24a3a9ebd8aca06778aba951d1ee0b448d4915f2..3d821993af4bbd1b42701c6122c8b1e6995fbc44 100644 (file)
@@ -85,10 +85,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
                                    (prop_info->flags & ZEND_ACC_STATIC) == 0 &&
                                    prop_info->offset >= 0 &&
                                    Z_TYPE(zobj->properties_table[prop_info->offset]) != IS_UNDEF) {
-                                       zval *zv = zend_hash_add(zobj->properties, prop_info->name, &zobj->properties_table[prop_info->offset]);
-                                       if (EXPECTED(zv != NULL)) {
-                                               ZVAL_INDIRECT(&zobj->properties_table[prop_info->offset], zv);
-                                       }
+                                       zval zv;
+
+                                       ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]);
+                                       zend_hash_add(zobj->properties, prop_info->name, &zv);
                                }
                        }
                        while (ce->parent && ce->parent->default_properties_count) {
@@ -101,10 +101,10 @@ ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
                                            (prop_info->flags & ZEND_ACC_PRIVATE) != 0 &&
                                            prop_info->offset >= 0 &&
                                                Z_TYPE(zobj->properties_table[prop_info->offset]) != IS_UNDEF) {
-                                               zval *zv = zend_hash_add(zobj->properties, prop_info->name, &zobj->properties_table[prop_info->offset]);
-                                               if (EXPECTED(zv != NULL)) {
-                                                       ZVAL_INDIRECT(&zobj->properties_table[prop_info->offset], zv);
-                                               }
+                                               zval zv;
+                                               
+                                               ZVAL_INDIRECT(&zv, &zobj->properties_table[prop_info->offset]);
+                                               zend_hash_add(zobj->properties, prop_info->name, &zv);
                                        }
                                }
                        }
@@ -133,15 +133,9 @@ ZEND_API HashTable *zend_std_get_gc(zval *object, zval **table, int *n TSRMLS_DC
        } else {
                zend_object *zobj = Z_OBJ_P(object);
 
-               if (zobj->properties) {
-                       *table = NULL;
-                       *n = 0;
-                       return zobj->properties;
-               } else {
-                       *table = zobj->properties_table;
-                       *n = zobj->ce->default_properties_count;
-                       return NULL;
-               }
+               *table = zobj->properties_table;
+               *n = zobj->ce->default_properties_count;
+               return zobj->properties;
        }
 }
 /* }}} */
@@ -454,20 +448,18 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li
 
        if (EXPECTED(property_info != NULL)) {
                if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0 &&
-                   Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
+                   property_info->offset >= 0) {
                        retval = &zobj->properties_table[property_info->offset];
-                       if (Z_TYPE_P(retval) == IS_INDIRECT) {
-                               retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) != IS_UNDEF) {
+                               goto exit;
                        }
-                       goto exit;
-               }
-               if (UNEXPECTED(zobj->properties != NULL)) {
+               } else if (UNEXPECTED(zobj->properties != NULL)) {
                        retval = zend_hash_find(zobj->properties, property_info->name);
                        if (retval) goto exit;
                }
        }
 
+       /* magic get */
        if (zobj->ce->__get) {
                long *guard = zend_get_property_guard(zobj, property_info, member);
                if (!((*guard) & IN_GET)) {
@@ -534,6 +526,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li
                }
                retval = &EG(uninitialized_zval);
        }
+
 exit:
        if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) {
                if (Z_REFCOUNTED_P(retval)) Z_ADDREF_P(retval);
@@ -565,15 +558,12 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, c
 
        if (EXPECTED(property_info != NULL)) {
                if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0 &&
-                   Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
+                   property_info->offset >= 0) {
                        variable_ptr = &zobj->properties_table[property_info->offset];
-                       if (Z_TYPE_P(variable_ptr) == IS_INDIRECT) {
-                               variable_ptr = Z_INDIRECT_P(variable_ptr);
+                       if (Z_TYPE_P(variable_ptr) != IS_UNDEF) {
+                               goto found;
                        }
-                       goto found;
-               }
-               if (EXPECTED(zobj->properties != NULL)) {
+               } else if (EXPECTED(zobj->properties != NULL)) {
                        if ((variable_ptr = zend_hash_find(zobj->properties, property_info->name)) != NULL) {
 found:
                                /* if we already have this value there, we don't actually need to do anything */
@@ -607,11 +597,12 @@ found:
                                                zval_ptr_dtor(&garbage);
                                        }
                                }
-                               return;
+                               goto exit;
                        }
                }
        }
 
+       /* magic set */
        if (zobj->ce->__set) {
                long *guard = zend_get_property_guard(zobj, property_info, member);
 
@@ -653,12 +644,7 @@ write_std_property:
                if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
                    property_info->offset >= 0) {
 
-                       if (zobj->properties) {
-                               zval *zv = zend_hash_update(zobj->properties, property_info->name, value);
-                           ZVAL_INDIRECT(&zobj->properties_table[property_info->offset], zv);
-                       } else {
-                               ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value);
-                       }
+                       ZVAL_COPY_VALUE(&zobj->properties_table[property_info->offset], value);
                } else {
                        if (!zobj->properties) {
                                rebuild_object_properties(zobj);
@@ -667,6 +653,7 @@ write_std_property:
                }
        }
 
+exit:
        if (UNEXPECTED(Z_TYPE(tmp_member) != IS_UNDEF)) {
                zval_ptr_dtor(&tmp_member);
        }
@@ -785,15 +772,12 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
 
        if (EXPECTED(property_info != NULL)) {
                if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0 &&
-                   Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
+                   property_info->offset >= 0) {
                        retval = &zobj->properties_table[property_info->offset];
-                       if (Z_TYPE_P(retval) == IS_INDIRECT) {
-                               retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) != IS_UNDEF) {
+                               goto exit;
                        }
-                       goto exit;
-               }
-               if (UNEXPECTED(zobj->properties != NULL)) {
+               } else if (UNEXPECTED(zobj->properties != NULL)) {
                        retval = zend_hash_find(zobj->properties, property_info->name);
                        if (retval) goto exit;
                }
@@ -810,13 +794,8 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
                ZVAL_NULL(&tmp);
                if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
                    property_info->offset >= 0) {
-                       if (zobj->properties) {                         
-                               retval = zend_hash_update(zobj->properties, property_info->name, &tmp);
-                           ZVAL_INDIRECT(&zobj->properties_table[property_info->offset], retval);
-                       } else {
-                               retval = &zobj->properties_table[property_info->offset];
-                               ZVAL_NULL(retval);
-                       }
+                       retval = &zobj->properties_table[property_info->offset];
+                       ZVAL_NULL(retval);
                } else {
                        if (!zobj->properties) {
                                rebuild_object_properties(zobj);
@@ -854,36 +833,39 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
 
        property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__unset != NULL), key TSRMLS_CC);
 
-       if (EXPECTED(property_info != NULL) &&
-           EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-           property_info->offset >= 0) {
-               zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
-               ZVAL_UNDEF(&zobj->properties_table[property_info->offset]);
-               if (!zobj->properties) goto exit;
+       if (EXPECTED(property_info != NULL)) {
+               if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+                   property_info->offset >= 0) {
+                       if (Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
+                               zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
+                               ZVAL_UNDEF(&zobj->properties_table[property_info->offset]);
+                               goto exit;
+                       }
+               } else if (zobj->properties &&
+               UNEXPECTED(zend_hash_del(zobj->properties, property_info->name) != FAILURE)) {
+                       goto exit;
+               }
        }
-       if (UNEXPECTED(!property_info) ||
-        !zobj->properties ||
-        UNEXPECTED(zend_hash_del(zobj->properties, property_info->name) == FAILURE)) {
        
-               if (zobj->ce->__unset) {
-                       long *guard = zend_get_property_guard(zobj, property_info, member);
-                       if (!((*guard) & IN_UNSET)) {
-                               /* have unseter - try with it! */
-                               Z_ADDREF_P(object);
-                               if (Z_ISREF_P(object)) {
-                                       SEPARATE_ZVAL(object);
-                               }
-                               (*guard) |= IN_UNSET; /* prevent circular unsetting */
-                               zend_std_call_unsetter(object, member TSRMLS_CC);
-                               (*guard) &= ~IN_UNSET;
-                               zval_ptr_dtor(object);
-                       } else {
-                               if (Z_STRVAL_P(member)[0] == '\0') {
-                                       if (Z_STRLEN_P(member) == 0) {
-                                               zend_error(E_ERROR, "Cannot access empty property");
-                                       } else {
-                                               zend_error(E_ERROR, "Cannot access property started with '\\0'");
-                                       }
+       /* magic unset */
+       if (zobj->ce->__unset) {
+               long *guard = zend_get_property_guard(zobj, property_info, member);
+               if (!((*guard) & IN_UNSET)) {
+                       /* have unseter - try with it! */
+                       Z_ADDREF_P(object);
+                       if (Z_ISREF_P(object)) {
+                               SEPARATE_ZVAL(object);
+                       }
+                       (*guard) |= IN_UNSET; /* prevent circular unsetting */
+                       zend_std_call_unsetter(object, member TSRMLS_CC);
+                       (*guard) &= ~IN_UNSET;
+                       zval_ptr_dtor(object);
+               } else {
+                       if (Z_STRVAL_P(member)[0] == '\0') {
+                               if (Z_STRLEN_P(member) == 0) {
+                                       zend_error(E_ERROR, "Cannot access empty property");
+                               } else {
+                                       zend_error(E_ERROR, "Cannot access property started with '\\0'");
                                }
                        }
                }
@@ -1382,12 +1364,6 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
                                        zval *p1 = &zobj1->properties_table[i];
                                        zval *p2 = &zobj2->properties_table[i];
 
-                                       if (Z_TYPE_P(p1) == IS_INDIRECT) {
-                                               p1 = Z_INDIRECT_P(p1);
-                                       }
-                                       if (Z_TYPE_P(p2) == IS_INDIRECT) {
-                                               p1 = Z_INDIRECT_P(p2);
-                                       }
                                        if (compare_function(&result, p1, p2 TSRMLS_CC)==FAILURE) {
                                                Z_OBJ_UNPROTECT_RECURSION(o1);
                                                Z_OBJ_UNPROTECT_RECURSION(o2);
@@ -1448,30 +1424,26 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
 
        if (EXPECTED(property_info != NULL)) {
                if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
-                   property_info->offset >= 0 &&
-                   Z_TYPE(zobj->properties_table[property_info->offset]) != IS_UNDEF) {
+                   property_info->offset >= 0) {
                        value = &zobj->properties_table[property_info->offset];
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
+                       if (Z_TYPE_P(value) != IS_UNDEF) {
+                               goto found;
                        }
-                       goto found;
-               }
-               if (UNEXPECTED(zobj->properties != NULL)) {
-                       if ((value = zend_hash_find(zobj->properties, property_info->name)) != NULL) {
+               } else if (UNEXPECTED(zobj->properties != NULL) &&
+                          (value = zend_hash_find(zobj->properties, property_info->name)) != NULL) {
 found:
-                               switch (has_set_exists) {
-                                       case 0:
-                                               result = (Z_TYPE_P(value) != IS_NULL);
-                                               break;
-                                       default:
-                                               result = zend_is_true(value TSRMLS_CC);
-                                               break;
-                                       case 2:
-                                               result = 1;
-                                               break;
-                               }
-                               goto exit;
+                       switch (has_set_exists) {
+                               case 0:
+                                       result = (Z_TYPE_P(value) != IS_NULL);
+                                       break;
+                               default:
+                                       result = zend_is_true(value TSRMLS_CC);
+                                       break;
+                               case 2:
+                                       result = 1;
+                                       break;
                        }
+                       goto exit;
                }
        }
 
index 50785b86ec8fc56f3f9b767ea62e2a189e82fd26..ec353b7a2c8bf4804f7e38a774716d7bb66b1c42 100644 (file)
@@ -142,32 +142,39 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
 {
        int i;
 
-       if (!old_object->properties) {
+       if (old_object->ce->default_properties_count) {
                for (i = 0; i < old_object->ce->default_properties_count; i++) {
                        zval_ptr_dtor(&new_object->properties_table[i]);
                        ZVAL_COPY(&new_object->properties_table[i], &old_object->properties_table[i]);
                }
-       } else {
+       }
+       if (old_object->properties) {
+               HashPosition pos;
+               zval *prop, new_prop;
+               ulong num_key;
+               zend_string *key;
+
                if (!new_object->properties) {
                        ALLOC_HASHTABLE(new_object->properties);
                        zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
                }
-               zend_hash_copy(new_object->properties, old_object->properties, zval_add_ref_unref);
-               if (old_object->properties_table) {
-                       HashPosition pos;
-                       zval *prop;
-                       zend_property_info *prop_info;
-
-                       for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos);
-                            (prop_info = zend_hash_get_current_data_ptr_ex(&old_object->ce->properties_info, &pos)) != NULL;
-                            zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) {
-                               if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
-                                       if ((prop = zend_hash_find(new_object->properties, prop_info->name)) != NULL) {
-                                               ZVAL_INDIRECT(&new_object->properties_table[prop_info->offset], prop);
-                                       } else {
-                                               ZVAL_UNDEF(&new_object->properties_table[prop_info->offset]);
-                                       }
-                               }
+
+               for (zend_hash_internal_pointer_reset_ex(old_object->properties, &pos);
+                    (prop = zend_hash_get_current_data_ex(old_object->properties, &pos)) != NULL;
+                    zend_hash_move_forward_ex(old_object->properties, &pos)) {
+                       if (Z_TYPE_P(prop) == IS_INDIRECT) {
+                               ZVAL_INDIRECT(&new_prop, new_object->properties_table + (Z_INDIRECT_P(prop) - old_object->properties_table));
+                       } else {
+                               ZVAL_COPY_VALUE(&new_prop, prop);
+                               zval_add_ref_unref(&new_prop);
+                       }
+                       switch (zend_hash_get_current_key_ex(old_object->properties, &key, &num_key, 0, &pos)) {
+                               case HASH_KEY_IS_STRING:
+                                       zend_hash_update(new_object->properties, key, &new_prop);
+                                       break;
+                               case HASH_KEY_IS_LONG:
+                                       zend_hash_index_update(new_object->properties, num_key, &new_prop);
+                                       break;
                        }
                }
        }
index f7375edc5ee0a9a6d0ab714ae6bb11678fa9ec7d..4a7fb4f74a80a629ac77c71bcb7e50befc6e78a2 100644 (file)
@@ -336,6 +336,18 @@ ZEND_API int zval_copy_static_var(zval *p TSRMLS_DC, int num_args, va_list args,
                                zend_error(E_NOTICE,"Undefined variable: %s", key->key->val);
                        }
                } else {
+                       if (Z_TYPE_P(p) == IS_INDIRECT) {
+                               p = Z_INDIRECT_P(p);
+                               if (Z_TYPE_P(p) == IS_UNDEF) {
+                                       if (!is_ref) {
+                                               zend_error(E_NOTICE,"Undefined variable: %s", key->key->val);
+                                               p = &tmp;
+                                               ZVAL_NULL(&tmp);
+                                       } else {
+                                               ZVAL_NULL(p);
+                                       }
+                               }
+                       }
                        if (is_ref) {
                                SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
                                Z_ADDREF_P(p);
index 37bd9107b704b358a9ae387e99aa32fe0f57c8b5..e97646be2eb570024629f7674d772b4524b0ed39 100644 (file)
@@ -340,17 +340,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (OP1_TYPE == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -1048,10 +1039,6 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
                FREE_OP1();
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (OP1_TYPE == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -1076,6 +1063,29 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -1860,9 +1870,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
        zend_bool nested = EX(nested);
        zend_op_array *op_array = EX(op_array);
 
+       if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) ||
+           EG(active_symbol_table) == &EG(symbol_table)) {
+               zend_detach_symbol_table(TSRMLS_C);
+       }
+       
        EG(current_execute_data) = EX(prev_execute_data);
        EG(opline_ptr) = NULL;
-       if (!EG(active_symbol_table)) {
+       
+       if (EG(active_symbol_table) != &EG(symbol_table)) {
                i_free_compiled_variables(execute_data TSRMLS_CC);
        }
 
@@ -1882,6 +1898,8 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                LOAD_OPLINE();
                if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
 
+                       zend_attach_symbol_table(TSRMLS_C);
+
                        EX(function_state).function = (zend_function *) EX(op_array);
                        EX(function_state).arguments = NULL;
 
@@ -3027,11 +3045,6 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
                zval_ptr_dtor(EX_VAR_NUM(opline->op2.var));
        }
        ZVAL_OBJ(EX_VAR_NUM(opline->op2.var), EG(exception));
-       if (EG(active_symbol_table)) {
-               zend_string *cv = CV_DEF_OF(opline->op2.var);
-               zval *zv = zend_hash_update(&EG(active_symbol_table)->ht, cv, EX_VAR_NUM(opline->op2.var));
-               ZVAL_INDIRECT(EX_VAR_NUM(opline->op2.var), zv);
-       }
        if (UNEXPECTED(EG(exception) != exception)) {
                EG(exception)->gc.refcount++;
                HANDLE_EXCEPTION();
@@ -3222,7 +3235,7 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
        args = GET_OP1_ZVAL_PTR(BP_VAR_R);
        arg_num = opline->op2.num + EX(call)->num_additional_args + 1;
 
-again:
+ZEND_VM_C_LABEL(send_again):
        switch (Z_TYPE_P(args)) {
                case IS_ARRAY: {
                        HashTable *ht = Z_ARRVAL_P(args);
@@ -3350,7 +3363,7 @@ ZEND_VM_C_LABEL(unpack_iter_dtor):
                }
                case IS_REFERENCE:
                        args = Z_REFVAL_P(args);
-                       goto again;
+                       ZEND_VM_C_GOTO(send_again);
                        break;
                default:
                        zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
@@ -3419,10 +3432,6 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
                                        
                        ZVAL_COPY_VALUE(&tmp, opline->op2.zv);
                        zval_update_constant(&tmp, 0 TSRMLS_CC);
-//???: var_ptr may become INDIRECT
-                       if (Z_TYPE_P(var_ptr) == IS_INDIRECT) {
-                               var_ptr = Z_INDIRECT_P(var_ptr);
-                       }
                        ZVAL_COPY_VALUE(var_ptr, &tmp);
                } else {
                        ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
@@ -3467,10 +3476,6 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
        for (; arg_num <= arg_count; ++arg_num) {
                zval *param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
                zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC);
-//??? "params" may became IS_INDIRECT because of symtable initialization in zend_error
-               if (Z_TYPE_P(params) == IS_INDIRECT) {
-                       params = Z_INDIRECT_P(params);
-               }
                zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
                if (Z_REFCOUNTED_P(param)) {
                        Z_ADDREF_P(param);
@@ -3805,7 +3810,7 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
                zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
                ulong hval;
 
-again:
+ZEND_VM_C_LABEL(add_again):
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -3827,7 +3832,7 @@ ZEND_VM_C_LABEL(num_index):
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               ZEND_VM_C_GOTO(add_again);
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -3877,7 +3882,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
                }
        }
 
-again:
+ZEND_VM_C_LABEL(cast_again):
        switch (opline->extended_value) {
                case IS_NULL:
                        convert_to_null(result);
@@ -3917,7 +3922,7 @@ again:
                        break;
                case IS_REFERENCE:
                        result = Z_REFVAL_P(result);
-                       goto again;
+                       ZEND_VM_C_GOTO(cast_again);
                        break;
        }
        FREE_OP1_IF_VAR();
@@ -4061,15 +4066,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
        if (OP1_TYPE == IS_CV &&
            OP2_TYPE == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -4112,11 +4110,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((OP1_TYPE == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (OP1_TYPE == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (OP1_TYPE != IS_CONST && varname == &tmp) {
@@ -4145,12 +4139,11 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
        offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
        if (OP1_TYPE != IS_VAR || container) {
-//???deref
-container_again:
+ZEND_VM_C_LABEL(container_again):
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
                                HashTable *ht = Z_ARRVAL_P(container);
-offset_again:
+ZEND_VM_C_LABEL(offset_again):
                                switch (Z_TYPE_P(offset)) {
                                        case IS_DOUBLE:
                                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -4189,7 +4182,7 @@ ZEND_VM_C_LABEL(num_index_dim):
                                                break;
                                        case IS_REFERENCE:
                                                offset = Z_REFVAL_P(offset);
-                                               goto offset_again;
+                                               ZEND_VM_C_GOTO(offset_again);
                                                break;
                                        default:
                                                zend_error(E_WARNING, "Illegal offset type in unset");
@@ -4221,7 +4214,7 @@ ZEND_VM_C_LABEL(num_index_dim):
                                ZEND_VM_CONTINUE(); /* bailed out before */
                        case IS_REFERENCE:
                                container = Z_REFVAL_P(container);
-                               goto container_again;
+                               ZEND_VM_C_GOTO(container_again);
                                break;
                        default:
                                FREE_OP2();
@@ -4492,16 +4485,28 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
 
                        fe_ht = Z_OBJPROP_P(array);
                        zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
-                       do {
+                       while (1) {
                                if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
                                        /* reached end of iteration */
                                        ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
                                }
+
+                               if (Z_TYPE_P(value) == IS_INDIRECT) {
+                                       value = Z_INDIRECT_P(value);
+                                       if (Z_TYPE_P(value) == IS_UNDEF) {
+                                               zend_hash_move_forward(fe_ht);
+                                               continue;
+                                       }
+                               }
+
                                key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &int_key, 0, NULL);
 
                                zend_hash_move_forward(fe_ht);
-                       } while (key_type != HASH_KEY_IS_LONG &&
-                                zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
+                               if (key_type == HASH_KEY_IS_LONG ||
+                                   zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+                                       break;
+                               }
+                       }
 
                        if (key) {
                                if (key_type == HASH_KEY_IS_LONG) {
@@ -4599,18 +4604,9 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -4648,10 +4644,6 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (OP1_TYPE == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -4704,7 +4696,7 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
 
                ht = Z_ARRVAL_P(container);
 
-again:
+ZEND_VM_C_LABEL(isset_again):
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -4722,18 +4714,18 @@ ZEND_VM_C_LABEL(num_index_prop):
                                if (OP2_TYPE != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, ZEND_VM_C_GOTO(num_index_prop));
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               ZEND_VM_C_GOTO(isset_again);
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
index c61ad640450241df0dbc99ce171a029ff512dd90..2ebff4738d424b7408f727132df0ad5c86292bf9 100644 (file)
@@ -386,9 +386,15 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
        zend_bool nested = EX(nested);
        zend_op_array *op_array = EX(op_array);
 
+       if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) ||
+           EG(active_symbol_table) == &EG(symbol_table)) {
+               zend_detach_symbol_table(TSRMLS_C);
+       }
+
        EG(current_execute_data) = EX(prev_execute_data);
        EG(opline_ptr) = NULL;
-       if (!EG(active_symbol_table)) {
+
+       if (EG(active_symbol_table) != &EG(symbol_table)) {
                i_free_compiled_variables(execute_data TSRMLS_CC);
        }
 
@@ -408,6 +414,8 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                LOAD_OPLINE();
                if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
 
+                       zend_attach_symbol_table(TSRMLS_C);
+
                        EX(function_state).function = (zend_function *) EX(op_array);
                        EX(function_state).arguments = NULL;
 
@@ -702,7 +710,7 @@ static int ZEND_FASTCALL  ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        args = get_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, BP_VAR_R);
        arg_num = opline->op2.num + EX(call)->num_additional_args + 1;
 
-again:
+send_again:
        switch (Z_TYPE_P(args)) {
                case IS_ARRAY: {
                        HashTable *ht = Z_ARRVAL_P(args);
@@ -830,7 +838,7 @@ unpack_iter_dtor:
                }
                case IS_REFERENCE:
                        args = Z_REFVAL_P(args);
-                       goto again;
+                       goto send_again;
                        break;
                default:
                        zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
@@ -902,10 +910,6 @@ static int ZEND_FASTCALL  ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
        for (; arg_num <= arg_count; ++arg_num) {
                zval *param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);
                zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC);
-//??? "params" may became IS_INDIRECT because of symtable initialization in zend_error
-               if (Z_TYPE_P(params) == IS_INDIRECT) {
-                       params = Z_INDIRECT_P(params);
-               }
                zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
                if (Z_REFCOUNTED_P(param)) {
                        Z_ADDREF_P(param);
@@ -1616,10 +1620,6 @@ static int ZEND_FASTCALL  ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
 
                        ZVAL_COPY_VALUE(&tmp, opline->op2.zv);
                        zval_update_constant(&tmp, 0 TSRMLS_CC);
-//???: var_ptr may become INDIRECT
-                       if (Z_TYPE_P(var_ptr) == IS_INDIRECT) {
-                               var_ptr = Z_INDIRECT_P(var_ptr);
-                       }
                        ZVAL_COPY_VALUE(var_ptr, &tmp);
                } else {
                        ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
@@ -2814,7 +2814,7 @@ static int ZEND_FASTCALL  ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                }
        }
 
-again:
+cast_again:
        switch (opline->extended_value) {
                case IS_NULL:
                        convert_to_null(result);
@@ -2854,7 +2854,7 @@ again:
                        break;
                case IS_REFERENCE:
                        result = Z_REFVAL_P(result);
-                       goto again;
+                       goto cast_again;
                        break;
        }
 
@@ -3603,10 +3603,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
 
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -3631,6 +3627,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -4013,7 +4032,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_O
                zval *offset = opline->op2.zv;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -4035,7 +4054,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -4079,15 +4098,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
        if (IS_CONST == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -4130,11 +4142,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_CONST != IS_CONST && varname == &tmp) {
@@ -4159,18 +4167,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -4208,10 +4207,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -4868,7 +4863,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC
                zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -4890,7 +4885,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -5381,10 +5376,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
 
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -5409,6 +5400,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -5677,7 +5691,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC
                zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -5699,7 +5713,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -5743,15 +5757,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
        if (IS_CONST == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -5794,11 +5801,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_CONST != IS_CONST && varname == &tmp) {
@@ -5823,18 +5826,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -5872,10 +5866,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -6088,10 +6078,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
 
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -6116,6 +6102,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -6352,7 +6361,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_
                zval *offset = NULL;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -6374,7 +6383,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -6418,15 +6427,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
        if (IS_CONST == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -6469,11 +6471,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_CONST != IS_CONST && varname == &tmp) {
@@ -6498,18 +6496,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -6547,10 +6536,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_CONST == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -7186,11 +7171,6 @@ static int ZEND_FASTCALL  ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
                zval_ptr_dtor(EX_VAR_NUM(opline->op2.var));
        }
        ZVAL_OBJ(EX_VAR_NUM(opline->op2.var), EG(exception));
-       if (EG(active_symbol_table)) {
-               zend_string *cv = CV_DEF_OF(opline->op2.var);
-               zval *zv = zend_hash_update(&EG(active_symbol_table)->ht, cv, EX_VAR_NUM(opline->op2.var));
-               ZVAL_INDIRECT(EX_VAR_NUM(opline->op2.var), zv);
-       }
        if (UNEXPECTED(EG(exception) != exception)) {
                EG(exception)->gc.refcount++;
                HANDLE_EXCEPTION();
@@ -7250,7 +7230,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO
                zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -7272,7 +7252,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -7906,7 +7886,7 @@ static int ZEND_FASTCALL  ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                }
        }
 
-again:
+cast_again:
        switch (opline->extended_value) {
                case IS_NULL:
                        convert_to_null(result);
@@ -7946,7 +7926,7 @@ again:
                        break;
                case IS_REFERENCE:
                        result = Z_REFVAL_P(result);
-                       goto again;
+                       goto cast_again;
                        break;
        }
 
@@ -8745,10 +8725,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
                zval_dtor(free_op1.var);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -8773,6 +8749,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -9063,7 +9062,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC
                zval *offset = opline->op2.zv;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -9085,7 +9084,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -9129,15 +9128,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
        if (IS_TMP_VAR == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -9180,11 +9172,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
@@ -9209,18 +9197,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -9258,10 +9237,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -9895,7 +9870,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD
                zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -9917,7 +9892,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -10408,10 +10383,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
                zval_dtor(free_op1.var);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -10436,6 +10407,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -10714,7 +10708,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
                zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -10736,7 +10730,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -10780,15 +10774,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_TMP_VAR == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -10831,11 +10818,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
@@ -10860,18 +10843,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -10909,10 +10883,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -11125,10 +11095,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
                zval_dtor(free_op1.var);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -11153,6 +11119,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -11278,7 +11267,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
                zval *offset = NULL;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -11300,7 +11289,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -11344,15 +11333,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
        if (IS_TMP_VAR == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -11395,11 +11377,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_TMP_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_TMP_VAR != IS_CONST && varname == &tmp) {
@@ -11424,18 +11402,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -11473,10 +11442,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_TMP_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -12107,7 +12072,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE
                zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -12129,7 +12094,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -13076,7 +13041,7 @@ static int ZEND_FASTCALL  ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                }
        }
 
-again:
+cast_again:
        switch (opline->extended_value) {
                case IS_NULL:
                        convert_to_null(result);
@@ -13116,7 +13081,7 @@ again:
                        break;
                case IS_REFERENCE:
                        result = Z_REFVAL_P(result);
-                       goto again;
+                       goto cast_again;
                        break;
        }
        zval_ptr_dtor_nogc(free_op1.var);
@@ -13464,16 +13429,28 @@ static int ZEND_FASTCALL  ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
 
                        fe_ht = Z_OBJPROP_P(array);
                        zend_hash_set_pointer(fe_ht, (HashPointer*)EX_VAR((opline+1)->op1.var));
-                       do {
+                       while (1) {
                                if ((value = zend_hash_get_current_data(fe_ht)) == NULL) {
                                        /* reached end of iteration */
                                        ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
                                }
+
+                               if (Z_TYPE_P(value) == IS_INDIRECT) {
+                                       value = Z_INDIRECT_P(value);
+                                       if (Z_TYPE_P(value) == IS_UNDEF) {
+                                               zend_hash_move_forward(fe_ht);
+                                               continue;
+                                       }
+                               }
+
                                key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &int_key, 0, NULL);
 
                                zend_hash_move_forward(fe_ht);
-                       } while (key_type != HASH_KEY_IS_LONG &&
-                                zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
+                               if (key_type == HASH_KEY_IS_LONG ||
+                                   zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+                                       break;
+                               }
+                       }
 
                        if (key) {
                                if (key_type == HASH_KEY_IS_LONG) {
@@ -13988,17 +13965,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -14475,10 +14443,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
                zval_ptr_dtor_nogc(free_op1.var);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -14503,6 +14467,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -15527,7 +15514,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC
                zval *offset = opline->op2.zv;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -15549,7 +15536,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -15593,15 +15580,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
        if (IS_VAR == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -15644,11 +15624,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_VAR != IS_CONST && varname == &tmp) {
@@ -15677,7 +15653,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
        offset = opline->op2.zv;
 
        if (IS_VAR != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -15821,18 +15796,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -15870,10 +15836,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -15926,7 +15888,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -15944,18 +15906,18 @@ num_index_prop:
                                if (IS_CONST != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -16483,17 +16445,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -17773,7 +17726,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD
                zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -17795,7 +17748,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -17844,7 +17797,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE
        offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
        if (IS_VAR != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -17999,7 +17951,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(in
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -18017,18 +17969,18 @@ num_index_prop:
                                if (IS_TMP_VAR != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -18556,17 +18508,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -19044,10 +18987,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
                zval_ptr_dtor_nogc(free_op1.var);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -19072,6 +19011,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -20066,7 +20028,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
                zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -20088,7 +20050,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -20132,15 +20094,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
        if (IS_VAR == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -20183,11 +20138,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_VAR != IS_CONST && varname == &tmp) {
@@ -20216,7 +20167,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
        offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
        if (IS_VAR != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -20360,18 +20310,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -20409,10 +20350,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -20465,7 +20402,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(in
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -20483,18 +20420,18 @@ num_index_prop:
                                if (IS_VAR != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -20747,17 +20684,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -21040,10 +20968,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
                zval_ptr_dtor_nogc(free_op1.var);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -21068,6 +20992,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -21491,7 +21438,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
                zval *offset = NULL;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -21513,7 +21460,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -21557,15 +21504,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
        if (IS_VAR == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -21608,11 +21548,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_VAR == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_VAR != IS_CONST && varname == &tmp) {
@@ -21637,18 +21573,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -21686,10 +21613,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_VAR == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -22167,17 +22090,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_VAR == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -23511,7 +23425,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE
                zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -23533,7 +23447,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -23582,7 +23496,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER
        offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
 
        if (IS_VAR != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -23737,7 +23650,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -23755,18 +23668,18 @@ num_index_prop:
                                if (IS_CV != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -24099,17 +24012,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -25070,7 +24974,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_H
        offset = opline->op2.zv;
 
        if (IS_UNUSED != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -25223,7 +25126,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CON
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -25241,18 +25144,18 @@ num_index_prop:
                                if (IS_CONST != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -25500,17 +25403,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -26388,7 +26282,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN
        offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
        if (IS_UNUSED != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -26541,7 +26434,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -26559,18 +26452,18 @@ num_index_prop:
                                if (IS_TMP_VAR != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -26818,17 +26711,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -27706,7 +27590,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN
        offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
        if (IS_UNUSED != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -27859,7 +27742,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -27877,18 +27760,18 @@ num_index_prop:
                                if (IS_VAR != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -28137,17 +28020,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -28552,17 +28426,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*b
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_UNUSED == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -29437,7 +29302,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND
        offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
 
        if (IS_UNUSED != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -29590,7 +29454,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -29608,18 +29472,18 @@ num_index_prop:
                                if (IS_CV != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -30597,7 +30461,7 @@ static int ZEND_FASTCALL  ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                }
        }
 
-again:
+cast_again:
        switch (opline->extended_value) {
                case IS_NULL:
                        convert_to_null(result);
@@ -30637,7 +30501,7 @@ again:
                        break;
                case IS_REFERENCE:
                        result = Z_REFVAL_P(result);
-                       goto again;
+                       goto cast_again;
                        break;
        }
 
@@ -31377,17 +31241,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -31863,10 +31718,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
 
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -31891,6 +31742,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -32704,7 +32578,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO
                zval *offset = opline->op2.zv;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -32726,7 +32600,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -32770,15 +32644,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
        if (IS_CV == IS_CV &&
            IS_CONST == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -32821,11 +32688,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_CV != IS_CONST && varname == &tmp) {
@@ -32854,7 +32717,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
        offset = opline->op2.zv;
 
        if (IS_CV != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -32996,18 +32858,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -33045,10 +32898,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -33101,7 +32950,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(i
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -33119,18 +32968,18 @@ num_index_prop:
                                if (IS_CONST != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -33654,17 +33503,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -34825,7 +34665,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE
                zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -34847,7 +34687,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -34896,7 +34736,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER
        offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
        if (IS_CV != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -35049,7 +34888,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -35067,18 +34906,18 @@ num_index_prop:
                                if (IS_TMP_VAR != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -35602,17 +35441,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -36089,10 +35919,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
 
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -36117,6 +35943,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -36992,7 +36841,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
                zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -37014,7 +36863,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -37058,15 +36907,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
        if (IS_CV == IS_CV &&
            IS_VAR == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -37109,11 +36951,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_CV != IS_CONST && varname == &tmp) {
@@ -37142,7 +36980,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
        offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC);
 
        if (IS_CV != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -37284,18 +37121,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -37333,10 +37161,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -37389,7 +37213,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -37407,18 +37231,18 @@ num_index_prop:
                                if (IS_VAR != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
@@ -37667,17 +37491,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*b
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -37959,10 +37774,6 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
 
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
 /*
                if (!target_symbol_table) {
                        CHECK_EXCEPTION();
@@ -37987,6 +37798,29 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
                                        break;
                                EMPTY_SWITCH_DEFAULT_CASE()
                        }
+//??? GLOBAL or $$name variable may be an INDIRECT pointer to CV
+               } else if (/*(opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_STATIC &&*/
+                       Z_TYPE_P(retval) == IS_INDIRECT) {
+                       retval = Z_INDIRECT_P(retval);
+                       if (Z_TYPE_P(retval) == IS_UNDEF) {
+                               switch (type) {
+                                       case BP_VAR_R:
+                                       case BP_VAR_UNSET:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_IS:
+                                               retval = EX_VAR(opline->result.var);
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       case BP_VAR_RW:
+                                               zend_error(E_NOTICE,"Undefined variable: %s", Z_STRVAL_P(varname));
+                                               /* break missing intentionally */
+                                       case BP_VAR_W:
+                                               ZVAL_NULL(retval);
+                                               break;
+                                       EMPTY_SWITCH_DEFAULT_CASE()
+                               }
+                       }
                }
                switch (opline->extended_value & ZEND_FETCH_TYPE_MASK) {
                        case ZEND_FETCH_GLOBAL:
@@ -38297,7 +38131,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
                zval *offset = NULL;
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -38319,7 +38153,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -38363,15 +38197,8 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
        if (IS_CV == IS_CV &&
            IS_UNUSED == IS_UNUSED &&
            (opline->extended_value & ZEND_QUICK_SET)) {
-               if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       zend_delete_variable(EX(prev_execute_data), &EG(active_symbol_table)->ht, cv TSRMLS_CC);
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               } else if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
-                       zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
-                       ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
-               }
+               zval_ptr_dtor(EX_VAR_NUM(opline->op1.var));
+               ZVAL_UNDEF(EX_VAR_NUM(opline->op1.var));
                CHECK_EXCEPTION();
                ZEND_VM_NEXT_OPCODE();
        }
@@ -38414,11 +38241,7 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
                zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? opline->op1.literal : NULL) TSRMLS_CC);
        } else {
                target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-               if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                       varname = Z_INDIRECT_P(varname);
-               }
-               zend_delete_variable(execute_data, target_symbol_table, Z_STR_P(varname) TSRMLS_CC);
+               zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
        }
 
        if (IS_CV != IS_CONST && varname == &tmp) {
@@ -38443,18 +38266,9 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
            (opline->extended_value & ZEND_QUICK_SET)) {
                if (Z_TYPE_P(EX_VAR_NUM(opline->op1.var)) != IS_UNDEF) {
                        value = EX_VAR_NUM(opline->op1.var);
-                       if (Z_TYPE_P(value) == IS_INDIRECT) {
-                               value = Z_INDIRECT_P(value);
-                       }
                        if (Z_TYPE_P(value) == IS_REFERENCE) {
                                value = Z_REFVAL_P(value);
                        }
-               } else if (EG(active_symbol_table)) {
-                       zend_string *cv = CV_DEF_OF(opline->op1.var);
-
-                       if ((value = zend_hash_find(&EG(active_symbol_table)->ht, cv)) == NULL) {
-                               isset = 0;
-                       }
                } else {
                        isset = 0;
                }
@@ -38492,10 +38306,6 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
                        }
                } else {
                        target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC);
-//???: STRING may become INDIRECT
-                       if (IS_CV == IS_CV && Z_TYPE_P(varname) == IS_INDIRECT) {
-                               varname = Z_INDIRECT_P(varname);
-                       }
                        if ((value = zend_hash_find(target_symbol_table, Z_STR_P(varname))) == NULL) {
                                isset = 0;
                        }
@@ -38953,17 +38763,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar
                zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
        }
 
-//???: object may become INDIRECT
-       if (IS_CV == IS_CV && Z_TYPE_P(object) == IS_INDIRECT) {
-               object = Z_INDIRECT_P(object);
-       }
-
        if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
                make_real_object(object TSRMLS_CC);
-//???
-               if (Z_TYPE_P(object) == IS_INDIRECT) {
-                       object = Z_INDIRECT_P(object);
-               }
        }
        if (UNEXPECTED(Z_ISREF_P(object))) {
                object = Z_REFVAL_P(object);
@@ -40177,7 +39978,7 @@ static int ZEND_FASTCALL  ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_
                zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
                ulong hval;
 
-again:
+add_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -40199,7 +40000,7 @@ num_index:
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto add_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type");
@@ -40248,7 +40049,6 @@ static int ZEND_FASTCALL  ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_
        offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC);
 
        if (IS_CV != IS_VAR || container) {
-//???deref
 container_again:
                switch (Z_TYPE_P(container)) {
                        case IS_ARRAY: {
@@ -40401,7 +40201,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int
 
                ht = Z_ARRVAL_P(container);
 
-again:
+isset_again:
                switch (Z_TYPE_P(offset)) {
                        case IS_DOUBLE:
                                hval = zend_dval_to_lval(Z_DVAL_P(offset));
@@ -40419,18 +40219,18 @@ num_index_prop:
                                if (IS_CV != IS_CONST) {
                                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, goto num_index_prop);
                                }
-                               if ((value = zend_hash_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_NULL:
-                               if ((value = zend_hash_find(ht, STR_EMPTY_ALLOC())) != NULL) {
+                               if ((value = zend_hash_find_ind(ht, STR_EMPTY_ALLOC())) != NULL) {
                                        isset = 1;
                                }
                                break;
                        case IS_REFERENCE:
                                offset = Z_REFVAL_P(offset);
-                               goto again;
+                               goto isset_again;
                                break;
                        default:
                                zend_error(E_WARNING, "Illegal offset type in isset or empty");
index 148dae43783a0e8a4ab53408581170b53b9ae8e0..53101b46239fc1c7de595a1776eac7f856efdac6 100644 (file)
@@ -223,14 +223,23 @@ static inline reflection_object *reflection_object_from_obj(zend_object *obj) /*
 
 static zend_object_handlers reflection_object_handlers;
 
+static zval *_default_load_entry(zval *object, char *name, int name_len TSRMLS_DC) /* {{{ */
+{
+       zval *value;
+
+       if ((value = zend_hash_str_find_ind(Z_OBJPROP_P(object), name, name_len)) == NULL) {
+               return NULL;
+       }
+       return value;
+}
+
 static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */
 {
        zval *value;
 
-       if ((value = zend_hash_str_find(Z_OBJPROP_P(object), name, name_len)) == NULL) {
+       if ((value = _default_load_entry(object, name, name_len TSRMLS_CC)) == NULL) {
                RETURN_FALSE;
        }
-
        ZVAL_DUP(return_value, value);
 }
 /* }}} */
@@ -3102,7 +3111,7 @@ ZEND_METHOD(reflection_function, inNamespace)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) {
+       if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) {
                RETURN_FALSE;
        }
        if (Z_TYPE_P(name) == IS_STRING
@@ -3125,7 +3134,7 @@ ZEND_METHOD(reflection_function, getNamespaceName)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) {
+       if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) {
                RETURN_FALSE;
        }
        if (Z_TYPE_P(name) == IS_STRING
@@ -3148,7 +3157,7 @@ ZEND_METHOD(reflection_function, getShortName)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) {
+       if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) {
                RETURN_FALSE;
        }
        if (Z_TYPE_P(name) == IS_STRING
@@ -4654,7 +4663,7 @@ ZEND_METHOD(reflection_class, inNamespace)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) {
+       if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) {
                RETURN_FALSE;
        }
        if (Z_TYPE_P(name) == IS_STRING
@@ -4677,7 +4686,7 @@ ZEND_METHOD(reflection_class, getNamespaceName)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) {
+       if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) {
                RETURN_FALSE;
        }
        if (Z_TYPE_P(name) == IS_STRING
@@ -4700,7 +4709,7 @@ ZEND_METHOD(reflection_class, getShortName)
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
-       if ((name = zend_hash_str_find(Z_OBJPROP_P(getThis()), "name", sizeof("name")-1)) == NULL) {
+       if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1) TSRMLS_CC) == NULL) {
                RETURN_FALSE;
        }
        if (Z_TYPE_P(name) == IS_STRING
@@ -4937,17 +4946,16 @@ ZEND_METHOD(reflection_property, getValue)
 {
        reflection_object *intern;
        property_reference *ref;
-       zval *object, name;
+       zval *object, *name;
        zval *member_p = NULL;
 
        METHOD_NOTSTATIC(reflection_property_ptr);
        GET_REFLECTION_OBJECT_PTR(ref);
 
        if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) {
-               _default_get_entry(getThis(), "name", sizeof("name")-1, &name TSRMLS_CC);
+               name = _default_load_entry(getThis(), "name", sizeof("name")-1 TSRMLS_CC);
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
-                       "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL(name));
-               zval_dtor(&name);
+                       "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL_P(name));
                return;
        }
 
@@ -4984,7 +4992,7 @@ ZEND_METHOD(reflection_property, setValue)
        reflection_object *intern;
        property_reference *ref;
        zval *variable_ptr;
-       zval *object, name;
+       zval *object, *name;
        zval *value;
        zval *tmp;
 
@@ -4992,10 +5000,9 @@ ZEND_METHOD(reflection_property, setValue)
        GET_REFLECTION_OBJECT_PTR(ref);
 
        if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
-               _default_get_entry(getThis(), "name", sizeof("name")-1, &name TSRMLS_CC);
+               name = _default_load_entry(getThis(), "name", sizeof("name")-1 TSRMLS_CC);
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
-                       "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL(name));
-               zval_dtor(&name);
+                       "Cannot access non-public member %s::%s", intern->ce->name->val, Z_STRVAL_P(name));
                return;
        }
 
index c6634ecf8a12a042cc047b3be142caf2421287d2..47f5fa2402e17e8fb0de7730eb784837737ffd2e 100644 (file)
@@ -324,7 +324,27 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval
        case IS_STRING:
           offset_key = Z_STR_P(offset);
 fetch_dim_string:
-               if ((retval = (zend_symtable_find(ht, offset_key))) == NULL) {
+               retval = zend_symtable_find(ht, offset_key);
+               if (retval) {
+                       if (Z_TYPE_P(retval) == IS_INDIRECT) {
+                               retval = Z_INDIRECT_P(retval);
+                               if (Z_TYPE_P(retval) == IS_UNDEF) {
+                                       switch (type) {
+                                               case BP_VAR_R:
+                                                       zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
+                                               case BP_VAR_UNSET:
+                                               case BP_VAR_IS:
+                                                       retval = &EG(uninitialized_zval);
+                                                       break;
+                                               case BP_VAR_RW:
+                                                       zend_error(E_NOTICE,"Undefined index: %s", offset_key->val);
+                                               case BP_VAR_W: {
+                                                       ZVAL_NULL(retval);
+                                               }
+                                       }
+                               }
+                       }
+               } else {
                        switch (type) {
                                case BP_VAR_R:
                                        zend_error(E_NOTICE, "Undefined index: %s", offset_key->val);
@@ -430,6 +450,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
 
        if (check_inherited && intern->fptr_offset_set) {
                zval tmp;
+
                if (!offset) {
                        ZVAL_NULL(&tmp);
                        offset = &tmp;
@@ -464,7 +485,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
                                zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
                                return;
                        }
-                       zend_symtable_update(ht, Z_STR_P(offset), value);
+                       zend_symtable_update_ind(ht, Z_STR_P(offset), value);
                        return;
                case IS_DOUBLE:
                case IS_RESOURCE:
@@ -526,36 +547,29 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
                                zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
                        }
                } else {
-                       if (zend_symtable_del(ht, Z_STR_P(offset)) == FAILURE) {
-                               zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
-                       } else {
-                               spl_array_object *obj = intern;
-
-                               while (1) {
-                                       if ((obj->ar_flags & SPL_ARRAY_IS_SELF) != 0) {
-                                               break;
-                                       } else if (Z_TYPE(obj->array) == IS_OBJECT) {
-                                           if ((obj->ar_flags & SPL_ARRAY_USE_OTHER) == 0) {
-                                                       obj = Z_SPLARRAY_P(&obj->array);
-                                               break;
-                                               } else {
-                                                       obj = Z_SPLARRAY_P(&obj->array);
-                                           }
+//??? see below
+#if 0
+                       if (zend_symtable_del_ind(ht, Z_STR_P(offset)) == FAILURE) {
+#else 
+                       zval *data = zend_symtable_find(ht, Z_STR_P(offset));
+
+                       if (data) {
+                               if (Z_TYPE_P(data) == IS_INDIRECT) {
+                                       data = Z_INDIRECT_P(data);
+                                       if (Z_TYPE_P(data) == IS_UNDEF) {
+                                               zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
                                        } else {
-                                               obj = NULL;
-                                               break;
-                                       }
-                               }
-                               if (obj) {
-                                       zend_property_info *property_info = zend_get_property_info(obj->std.ce, offset, 1 TSRMLS_CC);
-
-                                       if (property_info &&
-                                           (property_info->flags & ZEND_ACC_STATIC) == 0 &&
-                                           property_info->offset >= 0) {
-                                           zval_ptr_dtor(&obj->std.properties_table[property_info->offset]);
-                                               ZVAL_UNDEF(&obj->std.properties_table[property_info->offset]);
+                                               zval_ptr_dtor(data);
+                                               ZVAL_UNDEF(data);
                                        }
+//??? fix for ext/spl/tests/bug45614.phpt (may be fix is wrong)
+                                       spl_array_rewind(intern TSRMLS_CC);
+                               } else if (zend_symtable_del(ht, Z_STR_P(offset)) == FAILURE) {
+                                       zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
                                }
+                       } else {
+#endif
+                               zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
                        }
                }
                break;
@@ -610,7 +624,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
                case IS_STRING:
                        {
                                HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
-                               if ((tmp = zend_symtable_find(ht, Z_STR_P(offset))) != NULL) {
+                               if ((tmp = zend_symtable_find_ind(ht, Z_STR_P(offset))) != NULL) {
                                        switch (check_empty) {
                                                case 0:
                                                        return Z_TYPE_P(tmp) != IS_NULL;
@@ -919,11 +933,16 @@ static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSR
 {
        zend_string *string_key;
        ulong num_key;
+       zval *data;
 
        if (Z_TYPE(intern->array) == IS_OBJECT) {
                do {
                        if (zend_hash_get_current_key_ex(aht, &string_key, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) {
-                               if (!string_key->len || string_key->val[0]) {
+                               data = zend_hash_get_current_data_ex(aht, &intern->pos);
+                               if (data && Z_TYPE_P(data) == IS_INDIRECT &&
+                                   Z_TYPE_P(data = Z_INDIRECT_P(data)) == IS_UNDEF) {
+                                       /* skip */
+                               } else if (!string_key->len || string_key->val[0]) {
                                        return SUCCESS;
                                }
                        } else {
@@ -1002,7 +1021,11 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter TSRMLS_DC)
        if (object->ar_flags & SPL_ARRAY_OVERLOADED_CURRENT) {
                return zend_user_it_get_current_data(iter TSRMLS_CC);
        } else {
-               return zend_hash_get_current_data_ex(aht, &object->pos);
+               zval *data = zend_hash_get_current_data_ex(aht, &object->pos);
+               if (Z_TYPE_P(data) == IS_INDIRECT) {
+                       data = Z_INDIRECT_P(data);
+               }
+               return data;
        }
 }
 /* }}} */
@@ -1096,14 +1119,14 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar
                        ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;
                }
                ar_flags |= SPL_ARRAY_USE_OTHER;
-               intern->array = *array;
+               ZVAL_COPY_VALUE(&intern->array, array);
        } else {
                if (Z_TYPE_P(array) != IS_OBJECT && Z_TYPE_P(array) != IS_ARRAY) {
                        zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC);
                        return;
                }
                zval_ptr_dtor(&intern->array);
-               intern->array = *array;
+               ZVAL_COPY_VALUE(&intern->array, array);
        }
        if (Z_TYPE_P(array) == IS_OBJECT && Z_OBJ_P(object) == Z_OBJ_P(array)) {
                intern->ar_flags |= SPL_ARRAY_IS_SELF;
@@ -1507,6 +1530,12 @@ SPL_METHOD(Array, current)
        if ((entry = zend_hash_get_current_data_ex(aht, &intern->pos)) == NULL) {
                return;
        }
+       if (Z_TYPE_P(entry) == IS_INDIRECT) {
+               entry = Z_INDIRECT_P(entry);
+               if (Z_TYPE_P(entry) == IS_UNDEF) {
+                       return;
+               }
+       }
        RETVAL_ZVAL(entry, 1, 0);
 }
 /* }}} */
@@ -1765,10 +1794,7 @@ SPL_METHOD(Array, unserialize)
        }
 
        /* copy members */
-       if (!intern->std.properties) {
-               rebuild_object_properties(&intern->std);
-       }
-       zend_hash_copy(intern->std.properties, Z_ARRVAL(members), (copy_ctor_func_t) zval_add_ref);
+       object_properties_load(&intern->std, Z_ARRVAL(members));
        zval_ptr_dtor(&members);
 
        /* done reading $serialized */
index 84c5f87a434e0c767156a8c21ac7bf4a9c15ae86..e2a2f0233250c7a247825faf0f64c913f58a0e7d 100644 (file)
@@ -370,6 +370,12 @@ static int php_array_data_compare(const void *a, const void *b TSRMLS_DC) /* {{{
        first = &f->val;
        second = &s->val;
 
+       if (Z_TYPE_P(first) == IS_INDIRECT) {
+               first = Z_INDIRECT_P(first);
+       }
+       if (Z_TYPE_P(second) == IS_INDIRECT) {
+               second = Z_INDIRECT_P(second);
+       }
        if (ARRAYG(compare_func)(&result, first, second TSRMLS_CC) == FAILURE) {
                return 0;
        }
@@ -1056,6 +1062,13 @@ static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive
        /* Iterate through hash */
        zend_hash_internal_pointer_reset(target_hash);
        while (!EG(exception) && (zv = zend_hash_get_current_data(target_hash)) != NULL) {
+               if (Z_TYPE_P(zv) == IS_INDIRECT) {
+                       zv = Z_INDIRECT_P(zv);
+                       if (Z_TYPE_P(zv) == IS_UNDEF) {
+                               zend_hash_move_forward(target_hash);
+                               continue;
+                       }
+               }
                ZVAL_COPY(&args[0], zv);
                if (recursive &&
                    (Z_TYPE(args[0]) == IS_ARRAY ||
@@ -1332,6 +1345,14 @@ PHP_FUNCTION(extract)
        while ((entry = zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), &pos)) != NULL) {
                zval final_name;
 
+               if (Z_TYPE_P(entry) == IS_INDIRECT) {
+                       entry = Z_INDIRECT_P(entry);
+                       if (Z_TYPE_P(entry) == IS_UNDEF) {
+                               zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
+                               continue;
+                       }
+               }
+
                ZVAL_NULL(&final_name);
 
                key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &var_name, &num_key, 0, &pos);
@@ -1410,6 +1431,9 @@ PHP_FUNCTION(extract)
                                Z_ADDREF_P(entry);
 
                                if ((orig_var = zend_hash_find(&EG(active_symbol_table)->ht, Z_STR(final_name))) != NULL) {
+                                       if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
+                                               orig_var = Z_INDIRECT_P(orig_var);
+                                       }
                                        zval_ptr_dtor(orig_var);
                                        ZVAL_COPY_VALUE(orig_var, entry);
                                } else {
@@ -1417,7 +1441,7 @@ PHP_FUNCTION(extract)
                                }
                        } else {
                                ZVAL_DUP(&data, entry);
-                               ZEND_SET_SYMBOL_WITH_LENGTH(&EG(active_symbol_table)->ht, Z_STRVAL(final_name), Z_STRLEN(final_name), &data, 1, 0);
+                               zend_set_local_var(Z_STRVAL(final_name), Z_STRLEN(final_name), &data, 1 TSRMLS_CC);
                        }
                        count++;
                }
@@ -1442,12 +1466,11 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu
                entry = Z_REFVAL_P(entry);
        }
        if (Z_TYPE_P(entry) == IS_STRING) {
-               if ((value_ptr = zend_hash_find(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
+               if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
                        ZVAL_DUP(&data, value_ptr);
                        zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
                }
-       }
-       else if (Z_TYPE_P(entry) == IS_ARRAY) {
+       } else if (Z_TYPE_P(entry) == IS_ARRAY) {
                HashPosition pos;
 
                if ((Z_ARRVAL_P(entry)->nApplyCount > 1)) {
@@ -1459,6 +1482,13 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu
 
                zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(entry), &pos);
                while ((value_ptr = zend_hash_get_current_data_ex(Z_ARRVAL_P(entry), &pos)) != NULL) {
+                       if (Z_TYPE_P(value_ptr) == IS_INDIRECT) {
+                               value_ptr = Z_INDIRECT_P(value_ptr);
+                               if (Z_TYPE_P(value_ptr) == IS_UNDEF) {
+                                       zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos);
+                                       continue;
+                               }
+                       }
                        php_compact_var(eg_active_symbol_table, return_value, value_ptr TSRMLS_CC);
                        zend_hash_move_forward_ex(Z_ARRVAL_P(entry), &pos);
                }
@@ -1963,7 +1993,19 @@ static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
        } else {
                zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
        }
-       val = zend_hash_get_current_data(Z_ARRVAL_P(stack));
+       while (1) {
+               val = zend_hash_get_current_data(Z_ARRVAL_P(stack));
+               if (!val) {
+                       return;
+               } else if (Z_TYPE_P(val) == IS_INDIRECT) {
+                       val = Z_INDIRECT_P(val);
+                       if (Z_TYPE_P(val) == IS_UNDEF) {
+                               zend_hash_move_forward(Z_ARRVAL_P(stack));
+                               continue;
+                       }
+               }
+               break;
+       }
        RETVAL_ZVAL_FAST(val);
 
        /* Delete the first or last value */
@@ -2045,9 +2087,6 @@ PHP_FUNCTION(array_unshift)
         * hashtable and replace it with new one */
        new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[0], argc, NULL);
        old_hash = *Z_ARRVAL_P(stack);
-       if (Z_ARRVAL_P(stack) == &EG(symbol_table).ht) {
-               zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
-       }
        *Z_ARRVAL_P(stack) = *new_hash;
        FREE_HASHTABLE(new_hash);
        zend_hash_destroy(&old_hash);
@@ -2128,9 +2167,6 @@ PHP_FUNCTION(array_splice)
 
        /* Replace input array's hashtable with the new one */
        old_hash = *Z_ARRVAL_P(array);
-       if (Z_ARRVAL_P(array) == &EG(symbol_table).ht) {
-               zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
-       }
        *Z_ARRVAL_P(array) = *new_hash;
        FREE_HASHTABLE(new_hash);
        zend_hash_destroy(&old_hash);
@@ -2789,9 +2825,6 @@ PHP_FUNCTION(array_pad)
 
        /* Copy the result hash into return value */
        old_hash = *Z_ARRVAL_P(return_value);
-       if (Z_ARRVAL_P(return_value) == &EG(symbol_table).ht) {
-               zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
-       }
        *Z_ARRVAL_P(return_value) = *new_hash;
        FREE_HASHTABLE(new_hash);
        zend_hash_destroy(&old_hash);
@@ -2911,6 +2944,7 @@ PHP_FUNCTION(array_unique)
        for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) {
                p = Z_ARRVAL_P(array)->arData + idx;
                if (Z_TYPE(p->val) == IS_UNDEF) continue;
+               if (Z_TYPE(p->val) == IS_INDIRECT && Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) continue;
                arTmp[i].b = *p;
                arTmp[i].i = i;
                i++;
@@ -2954,6 +2988,12 @@ static int zval_compare(zval *a, zval *b TSRMLS_DC) /* {{{ */
        first = a;
        second = b;
 
+       if (Z_TYPE_P(first) == IS_INDIRECT) {
+               first = Z_INDIRECT_P(first);
+       }
+       if (Z_TYPE_P(second) == IS_INDIRECT) {
+               second = Z_INDIRECT_P(second);
+       }
        if (string_compare_function(&result, first, second TSRMLS_CC) == FAILURE) {
                return 0;
        }
@@ -2985,6 +3025,13 @@ static int zval_user_compare(zval *a, zval *b TSRMLS_DC) /* {{{ */
        zval args[2];
        zval retval;
 
+       if (Z_TYPE_P(a) == IS_INDIRECT) {
+               a = Z_INDIRECT_P(a);
+       }
+       if (Z_TYPE_P(b) == IS_INDIRECT) {
+               b = Z_INDIRECT_P(b);
+       }
+
        ZVAL_COPY_VALUE(&args[0], a);
        ZVAL_COPY_VALUE(&args[1], b);
 
index d666c025bb35082531d48cb8cab954cc42ce340a..2018c90b928526d28864d229d873fcafd203dcdf 100644 (file)
@@ -4265,13 +4265,16 @@ PHP_FUNCTION(getopt)
         * in order to be on the safe side, even though it is also available
         * from the symbol table. */
        if (Z_TYPE(PG(http_globals)[TRACK_VARS_SERVER]) != IS_UNDEF &&
-               ((args = zend_hash_str_find(HASH_OF(&PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv")-1)) != NULL ||
-               (args = zend_hash_str_find(&EG(symbol_table).ht, "argv", sizeof("argv")-1)) != NULL) && Z_TYPE_P(args) == IS_ARRAY
+               ((args = zend_hash_str_find_ind(HASH_OF(&PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv")-1)) != NULL ||
+               (args = zend_hash_str_find_ind(&EG(symbol_table).ht, "argv", sizeof("argv")-1)) != NULL)
        ) {
                int pos = 0;
                zval *entry;
 
-               argc = zend_hash_num_elements(Z_ARRVAL_P(args));
+               if (Z_TYPE_P(args) != IS_ARRAY) {
+                       RETURN_FALSE;
+               }
+               argc = zend_hash_num_elements(Z_ARRVAL_P(args));
 
                /* Attempt to allocate enough memory to hold all of the arguments
                 * and a trailing NULL */
index 62437f82d69795f02062c6108eca6ed80e8ec686..fc5727d7ce97565559881e1de1c3b26989ffd16c 100644 (file)
@@ -82,6 +82,12 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error traversing form data array");
                        return FAILURE;
                }
+               if (Z_TYPE_P(zdata) == IS_INDIRECT) {
+                       zdata = Z_INDIRECT_P(zdata);
+                       if (Z_TYPE_P(zdata) == IS_UNDEF) {
+                               continue;
+                       }
+               }
                if (Z_TYPE_P(zdata) == IS_ARRAY || Z_TYPE_P(zdata) == IS_OBJECT) {
                        if (key_type == HASH_KEY_IS_STRING) {
                                zend_string *ekey;
index 29e5db0ebf23ebf7c404b9af4c80a5a4df8df3a2..0fdba305592ab20e375cb210bb1f5be069348a70 100644 (file)
@@ -659,7 +659,7 @@ finish:
        if (header_init) {
                zval ztmp;
                array_init(&ztmp);
-               ZEND_SET_SYMBOL(&EG(active_symbol_table)->ht, "http_response_header", &ztmp);
+               zend_set_local_var("http_response_header", sizeof("http_response_header")-1, &ztmp, 0 TSRMLS_CC);
        }
 
        response_header = zend_hash_str_find(&EG(active_symbol_table)->ht, "http_response_header", sizeof("http_response_header")-1);
index 8c2694bef7dc13fe39f9fb96526488298b682c96..9ea1119cea6bb3045d29af7cc79bd6d132afb234 100644 (file)
 #define COMMON (is_ref ? "&" : "")
 /* }}} */
 
+static uint zend_obj_num_elements(HashTable *ht)
+{
+       Bucket *p;
+       uint idx;
+       uint num;
+
+       num = ht->nNumOfElements;
+       for (idx = 0; idx < ht->nNumUsed; idx++) {
+               p = ht->arData + idx;
+               if (Z_TYPE(p->val) == IS_UNDEF) continue;
+               if (Z_TYPE(p->val) == IS_INDIRECT) {
+                       if (Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) {
+                               num--;
+                       }                       
+               }
+       }
+       return num;
+}
+
 static int php_array_element_dump(zval *zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
        int level;
 
        level = va_arg(args, int);
 
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+               if (Z_TYPE_P(zv) == IS_UNDEF) {
+                       return 0;
+               }
+       }
        if (hash_key->key == NULL) { /* numeric key */
                php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
        } else { /* string key */
@@ -60,6 +85,12 @@ static int php_object_property_dump(zval *zv TSRMLS_DC, int num_args, va_list ar
 
        level = va_arg(args, int);
 
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+               if (Z_TYPE_P(zv) == IS_UNDEF) {
+                       return 0;
+               }
+       }
        if (hash_key->key == NULL) { /* numeric key */
                php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
        } else { /* string key */
@@ -136,10 +167,10 @@ again:
 
                        if (Z_OBJ_HANDLER_P(struc, get_class_name)) {
                                class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(struc, 0 TSRMLS_CC);
-                               php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_hash_num_elements(myht) : 0);
+                               php_printf("%sobject(%s)#%d (%d) {\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0);
                                STR_RELEASE(class_name);
                        } else {
-                               php_printf("%sobject(unknown class)#%d (%d) {\n", COMMON, Z_OBJ_HANDLE_P(struc), myht ? zend_hash_num_elements(myht) : 0);
+                               php_printf("%sobject(unknown class)#%d (%d) {\n", COMMON, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0);
                        }
                        php_element_dump_func = php_object_property_dump;
        head_done:
@@ -162,7 +193,7 @@ again:
                        break;
                }
                case IS_REFERENCE:
-       //??? hide references with refcount==1 (for compatibility)
+//??? hide references with refcount==1 (for compatibility)
                        if (Z_REFCOUNT_P(struc) > 1) {
                                is_ref = 1;
                        }
@@ -200,6 +231,12 @@ static int zval_array_element_dump(zval *zv TSRMLS_DC, int num_args, va_list arg
 
        level = va_arg(args, int);
 
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+               if (Z_TYPE_P(zv) == IS_UNDEF) {
+                       return 0;
+               }
+       }
        if (hash_key->key == NULL) { /* numeric key */
                php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
        } else { /* string key */
@@ -225,6 +262,12 @@ static int zval_object_property_dump(zval *zv TSRMLS_DC, int num_args, va_list a
 
        level = va_arg(args, int);
 
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+               if (Z_TYPE_P(zv) == IS_UNDEF) {
+                       return 0;
+               }
+       }
        if (hash_key->key == NULL) { /* numeric key */
                php_printf("%*c[%ld]=>\n", level + 1, ' ', hash_key->h);
        } else { /* string key */
@@ -259,14 +302,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level TSRMLS_DC) /* {{{ */
                php_printf("%*c", level - 1, ' ');
        }
 
-       if (Z_TYPE_P(struc) == IS_REFERENCE) {
-//??? hide references with refcount==1 (for compatibility)
-               if (Z_REFCOUNT_P(struc) > 1) {
-                       is_ref = 1;
-               }
-               struc = Z_REFVAL_P(struc);
-       }
-
+again:
        switch (Z_TYPE_P(struc)) {
        case IS_BOOL:
                php_printf("%sbool(%s)\n", COMMON, Z_LVAL_P(struc)?"true":"false");
@@ -301,7 +337,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level TSRMLS_DC) /* {{{ */
                        return;
                }
                class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(struc, 0 TSRMLS_CC);
-               php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_hash_num_elements(myht) : 0, Z_REFCOUNT_P(struc));
+               php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, class_name->val, Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0, Z_REFCOUNT_P(struc));
                STR_RELEASE(class_name);
                zval_element_dump_func = zval_object_property_dump;
 head_done:
@@ -322,6 +358,13 @@ head_done:
                php_printf("%sresource(%ld) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
                break;
        }
+       case IS_REFERENCE:
+//??? hide references with refcount==1 (for compatibility)
+               if (Z_REFCOUNT_P(struc) > 1) {
+                       is_ref = 1;
+               }
+               struc = Z_REFVAL_P(struc);
+               goto again;
        default:
                php_printf("%sUNKNOWN:0\n", COMMON);
                break;
@@ -364,6 +407,12 @@ static int php_array_element_export(zval *zv TSRMLS_DC, int num_args, va_list ar
        level = va_arg(args, int);
        buf = va_arg(args, smart_str *);
 
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+               if (Z_TYPE_P(zv) == IS_UNDEF) {
+                       return 0;
+               }
+       }
        if (hash_key->key == NULL) { /* numeric key */
                buffer_append_spaces(buf, level+1);
                smart_str_append_long(buf, (long) hash_key->h);
@@ -400,6 +449,13 @@ static int php_object_element_export(zval *zv TSRMLS_DC, int num_args, va_list a
        level = va_arg(args, int);
        buf = va_arg(args, smart_str *);
 
+       if (Z_TYPE_P(zv) == IS_INDIRECT) {
+               zv = Z_INDIRECT_P(zv);
+               if (Z_TYPE_P(zv) == IS_UNDEF) {
+                       return 0;
+               }
+       }
+
        buffer_append_spaces(buf, level + 2);
        if (hash_key->key != NULL) {
                const char *class_name; /* ignored, but must be passed to unmangle */
@@ -683,6 +739,12 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt
                        }
                        propers = Z_OBJPROP_P(struc);
                        if ((d = zend_hash_find(propers, Z_STR_P(name))) != NULL) {
+                               if (Z_TYPE_P(d) == IS_INDIRECT) {
+                                       d = Z_INDIRECT_P(d);
+                                       if (Z_TYPE_P(d) == IS_UNDEF) {
+                                               continue;
+                                       }
+                               }
                                php_var_serialize_string(buf, Z_STRVAL_P(name), Z_STRLEN_P(name));
                                php_var_serialize_intern(buf, d, var_hash TSRMLS_CC);
                        } else {
@@ -694,6 +756,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt
                                        do {
                                                priv_name = zend_mangle_property_name(ce->name->val, ce->name->len, Z_STRVAL_P(name), Z_STRLEN_P(name), ce->type & ZEND_INTERNAL_CLASS);
                                                if ((d = zend_hash_find(propers, priv_name)) != NULL) {
+                                                       if (Z_TYPE_P(d) == IS_INDIRECT) {
+                                                               d = Z_INDIRECT_P(d);
+                                                               if (Z_TYPE_P(d) == IS_UNDEF) {
+                                                                       STR_FREE(prot_name);
+                                                                       break;
+                                                               }
+                                                       }
                                                        php_var_serialize_string(buf, priv_name->val, priv_name->len);
                                                        STR_FREE(priv_name);
                                                        php_var_serialize_intern(buf, d, var_hash TSRMLS_CC);
@@ -702,6 +771,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt
                                                STR_FREE(priv_name);
                                                prot_name = zend_mangle_property_name("*", 1, Z_STRVAL_P(name), Z_STRLEN_P(name), ce->type & ZEND_INTERNAL_CLASS);
                                                if ((d = zend_hash_find(propers, prot_name)) != NULL) {
+                                                       if (Z_TYPE_P(d) == IS_INDIRECT) {
+                                                               d = Z_INDIRECT_P(d);
+                                                               if (Z_TYPE_P(d) == IS_UNDEF) {
+                                                                       STR_FREE(prot_name);
+                                                                       break;
+                                                               }
+                                                       }
                                                        php_var_serialize_string(buf, prot_name->val, prot_name->len);
                                                        STR_FREE(prot_name);
                                                        php_var_serialize_intern(buf, d, var_hash TSRMLS_CC);
@@ -873,10 +949,17 @@ again:
 
                                zend_hash_internal_pointer_reset_ex(myht, &pos);
                                for (;; zend_hash_move_forward_ex(myht, &pos)) {
-                                       i = zend_hash_get_current_key_ex(myht, &key, &index, 0, &pos);
-                                       if (i == HASH_KEY_NON_EXISTENT) {
+                                       data = zend_hash_get_current_data_ex(myht, &pos);
+                                       if (!data) {
                                                break;
+                                       } else if (Z_TYPE_P(data) == IS_INDIRECT) {
+                                               data = Z_INDIRECT_P(data);
+                                               if (Z_TYPE_P(data) == IS_UNDEF) {
+                                                       continue;
+                                               }
                                        }
+
+                                       i = zend_hash_get_current_key_ex(myht, &key, &index, 0, &pos);
                                        if (incomplete_class && strcmp(key->val, MAGIC_MEMBER) == 0) {
                                                continue;
                                        }
@@ -892,8 +975,7 @@ again:
 
                                        /* we should still add element even if it's not OK,
                                         * since we already wrote the length of the array before */
-                                       if ((data = zend_hash_get_current_data_ex(myht, &pos)) == NULL
-                                               || (Z_TYPE_P(data) == IS_ARRAY && Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))
+                                       if ((Z_TYPE_P(data) == IS_ARRAY && Z_TYPE_P(struc) == IS_ARRAY && Z_ARR_P(data) == Z_ARR_P(struc))
                                                || (Z_TYPE_P(data) == IS_ARRAY && Z_ARRVAL_P(data)->nApplyCount > 1)
                                        ) {
                                                smart_str_appendl(buf, "N;", 2);
index 8e69338b021072f77a58984e21c11f72b77caa92..13f645b58e165b2fec4040f91715457ad393fa1b 100644 (file)
@@ -79,7 +79,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
                (*var_hashx)->last_dtor = var_hash;
        }
 
-       Z_ADDREF_P(rval);
+       if (Z_REFCOUNTED_P(rval)) Z_ADDREF_P(rval);
        var_hash->data[var_hash->used_slots++] = rval;
 }
 
@@ -306,7 +306,21 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
                } else {
                        /* object properties should include no integers */
                        convert_to_string(&key);
-                       data = zend_hash_update(ht, Z_STR(key), &d);
+//???
+#if 1
+                       data = zend_hash_update_ind(ht, Z_STR(key), &d);
+#else
+                       if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) {
+                               if (Z_TYPE_P(data) == IS_INDIRECT) {
+                                       data = Z_INDIRECT_P(data);
+                               }
+                               zval_ptr_dtor(data);
+//???                          var_push_dtor(var_hash, data);
+                               ZVAL_UNDEF(data);
+                       } else {
+                               data = zend_hash_update(ht, Z_STR(key), &d);
+                       }
+#endif
                }
                
                zval_dtor(&key);
@@ -428,7 +442,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER)
        start = cursor;
 
 
-#line 432 "ext/standard/var_unserializer.c"
+#line 446 "ext/standard/var_unserializer.c"
 {
        YYCTYPE yych;
        static const unsigned char yybm[] = {
@@ -488,9 +502,9 @@ yy2:
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych == ':') goto yy95;
 yy3:
-#line 778 "ext/standard/var_unserializer.re"
+#line 792 "ext/standard/var_unserializer.re"
        { return 0; }
-#line 494 "ext/standard/var_unserializer.c"
+#line 508 "ext/standard/var_unserializer.c"
 yy4:
        yych = *(YYMARKER = ++YYCURSOR);
        if (yych == ':') goto yy89;
@@ -533,13 +547,13 @@ yy13:
        goto yy3;
 yy14:
        ++YYCURSOR;
-#line 772 "ext/standard/var_unserializer.re"
+#line 786 "ext/standard/var_unserializer.re"
        {
        /* this is the case where we have less data than planned */
        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data");
        return 0; /* not sure if it should be 0 or 1 here? */
 }
-#line 543 "ext/standard/var_unserializer.c"
+#line 557 "ext/standard/var_unserializer.c"
 yy16:
        yych = *++YYCURSOR;
        goto yy3;
@@ -569,7 +583,7 @@ yy20:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 633 "ext/standard/var_unserializer.re"
+#line 647 "ext/standard/var_unserializer.re"
        {
        size_t len, len2, len3, maxlen;
        long elements;
@@ -708,7 +722,7 @@ yy20:
 
        return object_common2(UNSERIALIZE_PASSTHRU, elements);
 }
-#line 712 "ext/standard/var_unserializer.c"
+#line 726 "ext/standard/var_unserializer.c"
 yy25:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -733,7 +747,7 @@ yy27:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 625 "ext/standard/var_unserializer.re"
+#line 639 "ext/standard/var_unserializer.re"
        {
 
 //???  INIT_PZVAL(rval);
@@ -741,7 +755,7 @@ yy27:
        return object_common2(UNSERIALIZE_PASSTHRU,
                        object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR));
 }
-#line 745 "ext/standard/var_unserializer.c"
+#line 759 "ext/standard/var_unserializer.c"
 yy32:
        yych = *++YYCURSOR;
        if (yych == '+') goto yy33;
@@ -762,7 +776,7 @@ yy34:
        yych = *++YYCURSOR;
        if (yych != '{') goto yy18;
        ++YYCURSOR;
-#line 604 "ext/standard/var_unserializer.re"
+#line 618 "ext/standard/var_unserializer.re"
        {
        long elements = parse_iv(start + 2);
        /* use iv() not uiv() in order to check data range */
@@ -783,7 +797,7 @@ yy34:
 
        return finish_nested_data(UNSERIALIZE_PASSTHRU);
 }
-#line 787 "ext/standard/var_unserializer.c"
+#line 801 "ext/standard/var_unserializer.c"
 yy39:
        yych = *++YYCURSOR;
        if (yych == '+') goto yy40;
@@ -804,7 +818,7 @@ yy41:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 574 "ext/standard/var_unserializer.re"
+#line 588 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
 //??? TODO: use zend_string* instead of char*
@@ -834,7 +848,7 @@ yy41:
        efree(str);
        return 1;
 }
-#line 838 "ext/standard/var_unserializer.c"
+#line 852 "ext/standard/var_unserializer.c"
 yy46:
        yych = *++YYCURSOR;
        if (yych == '+') goto yy47;
@@ -855,7 +869,7 @@ yy48:
        yych = *++YYCURSOR;
        if (yych != '"') goto yy18;
        ++YYCURSOR;
-#line 547 "ext/standard/var_unserializer.re"
+#line 561 "ext/standard/var_unserializer.re"
        {
        size_t len, maxlen;
        char *str;
@@ -882,7 +896,7 @@ yy48:
        ZVAL_STRINGL(rval, str, len);
        return 1;
 }
-#line 886 "ext/standard/var_unserializer.c"
+#line 900 "ext/standard/var_unserializer.c"
 yy53:
        yych = *++YYCURSOR;
        if (yych <= '/') {
@@ -970,7 +984,7 @@ yy61:
        }
 yy63:
        ++YYCURSOR;
-#line 538 "ext/standard/var_unserializer.re"
+#line 552 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_LONG == 4
 use_double:
@@ -979,7 +993,7 @@ use_double:
        ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL));
        return 1;
 }
-#line 983 "ext/standard/var_unserializer.c"
+#line 997 "ext/standard/var_unserializer.c"
 yy65:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1038,7 +1052,7 @@ yy73:
        yych = *++YYCURSOR;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 522 "ext/standard/var_unserializer.re"
+#line 536 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
 
@@ -1054,7 +1068,7 @@ yy73:
 
        return 1;
 }
-#line 1058 "ext/standard/var_unserializer.c"
+#line 1072 "ext/standard/var_unserializer.c"
 yy76:
        yych = *++YYCURSOR;
        if (yych == 'N') goto yy73;
@@ -1081,7 +1095,7 @@ yy79:
        if (yych <= '9') goto yy79;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 496 "ext/standard/var_unserializer.re"
+#line 510 "ext/standard/var_unserializer.re"
        {
 #if SIZEOF_LONG == 4
        int digits = YYCURSOR - start - 3;
@@ -1107,7 +1121,7 @@ yy79:
        ZVAL_LONG(rval, parse_iv(start + 2));
        return 1;
 }
-#line 1111 "ext/standard/var_unserializer.c"
+#line 1125 "ext/standard/var_unserializer.c"
 yy83:
        yych = *++YYCURSOR;
        if (yych <= '/') goto yy18;
@@ -1115,22 +1129,22 @@ yy83:
        yych = *++YYCURSOR;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 490 "ext/standard/var_unserializer.re"
+#line 504 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_BOOL(rval, parse_iv(start + 2));
        return 1;
 }
-#line 1125 "ext/standard/var_unserializer.c"
+#line 1139 "ext/standard/var_unserializer.c"
 yy87:
        ++YYCURSOR;
-#line 484 "ext/standard/var_unserializer.re"
+#line 498 "ext/standard/var_unserializer.re"
        {
        *p = YYCURSOR;
        ZVAL_NULL(rval);
        return 1;
 }
-#line 1134 "ext/standard/var_unserializer.c"
+#line 1148 "ext/standard/var_unserializer.c"
 yy89:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1153,7 +1167,7 @@ yy91:
        if (yych <= '9') goto yy91;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 461 "ext/standard/var_unserializer.re"
+#line 475 "ext/standard/var_unserializer.re"
        {
        long id;
 
@@ -1176,7 +1190,7 @@ yy91:
        
        return 1;
 }
-#line 1180 "ext/standard/var_unserializer.c"
+#line 1194 "ext/standard/var_unserializer.c"
 yy95:
        yych = *++YYCURSOR;
        if (yych <= ',') {
@@ -1199,7 +1213,7 @@ yy97:
        if (yych <= '9') goto yy97;
        if (yych != ';') goto yy18;
        ++YYCURSOR;
-#line 436 "ext/standard/var_unserializer.re"
+#line 450 "ext/standard/var_unserializer.re"
        {
        long id;
 
@@ -1224,9 +1238,9 @@ yy97:
        
        return 1;
 }
-#line 1228 "ext/standard/var_unserializer.c"
+#line 1242 "ext/standard/var_unserializer.c"
 }
-#line 780 "ext/standard/var_unserializer.re"
+#line 794 "ext/standard/var_unserializer.re"
 
 
        return 0;
index ae195ae88bf7491946e40f3563f689804383c82c..cda2dcd4528f0f06be1fdcae390131175e9fdc6e 100644 (file)
@@ -77,7 +77,7 @@ PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
                (*var_hashx)->last_dtor = var_hash;
        }
 
-       Z_ADDREF_P(rval);
+       if (Z_REFCOUNTED_P(rval)) Z_ADDREF_P(rval);
        var_hash->data[var_hash->used_slots++] = rval;
 }
 
@@ -310,7 +310,21 @@ static inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, long
                } else {
                        /* object properties should include no integers */
                        convert_to_string(&key);
-                       data = zend_hash_update(ht, Z_STR(key), &d);
+//???
+#if 1
+                       data = zend_hash_update_ind(ht, Z_STR(key), &d);
+#else
+                       if ((data = zend_hash_find(ht, Z_STR(key))) != NULL) {
+                               if (Z_TYPE_P(data) == IS_INDIRECT) {
+                                       data = Z_INDIRECT_P(data);
+                               }
+                               zval_ptr_dtor(data);
+//???                          var_push_dtor(var_hash, data);
+                               ZVAL_UNDEF(data);
+                       } else {
+                               data = zend_hash_update(ht, Z_STR(key), &d);
+                       }
+#endif
                }
                
                zval_dtor(&key);
index 0f8a029b51392252ff146388e1145753b2fd2b60..931a5246c6536fb469cda39611544a5db41b7ef3 100644 (file)
@@ -857,13 +857,10 @@ PHPAPI void php_verror(const char *docref, const char *params, int type, const c
 
        if (PG(track_errors) && module_initialized &&
                        (Z_TYPE(EG(user_error_handler)) == IS_UNDEF || !(EG(user_error_handler_error_reporting) & type))) {
-               if (!EG(active_symbol_table)) {
-                       zend_rebuild_symbol_table(TSRMLS_C);
-               }
-               if (EG(active_symbol_table)) {
-                       zval tmp;
-                       ZVAL_STRINGL(&tmp, buffer, buffer_len);
-                       zend_hash_str_update(&EG(active_symbol_table)->ht, "php_errormsg", sizeof("php_errormsg")-1, &tmp);
+               zval tmp;
+               ZVAL_STRINGL(&tmp, buffer, buffer_len);
+               if (zend_set_local_var("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) {
+                       zval_ptr_dtor(&tmp);
                }
        }
        if (replace_buffer) {
@@ -1195,7 +1192,9 @@ static void php_error_cb(int type, const char *error_filename, const uint error_
                if (EG(active_symbol_table)) {
                        zval tmp;
                        ZVAL_STRINGL(&tmp, buffer, buffer_len);
-                       zend_hash_str_update(&EG(active_symbol_table)->ht, "php_errormsg", sizeof("php_errormsg")-1, &tmp);
+                       if (zend_set_local_var("php_errormsg", sizeof("php_errormsg")-1, &tmp, 0 TSRMLS_CC) == FAILURE) {
+                               zval_ptr_dtor(&tmp);
+                       }
                }
        }
 
index 47b2c522bde0ff92ae55886602dc0fccb7e6c0d4..20bee7e8d9fbcd0f89457cb9fb2d18df5e9fb194 100644 (file)
@@ -181,10 +181,19 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
                                        return;
                                }
                        } else {
-                               if ((gpc_element_p = zend_symtable_str_find(symtable1, index, index_len)) == NULL
-                                       || Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
-                                       array_init(&gpc_element);
-                                       gpc_element_p = zend_symtable_str_update(symtable1, index, index_len, &gpc_element);
+                               gpc_element_p = zend_symtable_str_find(symtable1, index, index_len);
+                               if (!gpc_element_p) {
+                                       zval tmp;
+                                       array_init(&tmp);
+                                       gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &tmp);
+                               } else {
+                                       if (Z_TYPE_P(gpc_element_p) == IS_INDIRECT) {
+                                               gpc_element_p = Z_INDIRECT_P(gpc_element_p);
+                                       }
+                                       if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) {
+                                               zval_ptr_dtor(gpc_element_p);
+                                               array_init(gpc_element_p);
+                                       }
                                }
                        }
                        symtable1 = Z_ARRVAL_P(gpc_element_p);
@@ -219,7 +228,7 @@ plain_var:
                                zend_symtable_str_exists(symtable1, index, index_len)) {
                                zval_ptr_dtor(&gpc_element);
                        } else {
-                               gpc_element_p = zend_symtable_str_update(symtable1, index, index_len, &gpc_element);
+                               gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &gpc_element);
                        }
                }
        }