]> granicus.if.org Git - php/commitdiff
Added caches to eliminate repeatable run-time bindings of functions, classes, constan...
authorDmitry Stogov <dmitry@php.net>
Mon, 24 May 2010 14:11:39 +0000 (14:11 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 24 May 2010 14:11:39 +0000 (14:11 +0000)
45 files changed:
NEWS
Zend/bench.php
Zend/zend.h
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_exceptions.c
Zend/zend_execute.h
Zend/zend_object_handlers.c
Zend/zend_object_handlers.h
Zend/zend_objects.c
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
ext/date/php_date.c
ext/dom/php_dom.c
ext/fileinfo/fileinfo.c
ext/mysqli/mysqli.c
ext/pdo/pdo_dbh.c
ext/pdo/pdo_stmt.c
ext/reflection/php_reflection.c
ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001.phpt
ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt [new file with mode: 0644]
ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001.phpt
ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt [new file with mode: 0644]
ext/spl/spl_array.c
ext/spl/spl_directory.c
ext/spl/spl_dllist.c
ext/spl/spl_fixedarray.c
ext/spl/spl_heap.c
ext/spl/spl_iterators.c
ext/spl/spl_observer.c
ext/sqlite/sqlite.c
ext/sqlite3/sqlite3.c
ext/standard/incomplete_class.c
ext/standard/tests/array/array_fill_object.phpt
ext/standard/tests/array/array_fill_object_2_4.phpt [new file with mode: 0644]
ext/tidy/tidy.c
ext/xmlreader/php_xmlreader.c
ext/xmlwriter/php_xmlwriter.c
ext/xsl/php_xsl.c
ext/zip/php_zip.c

diff --git a/NEWS b/NEWS
index dafcefb57773348963353d299aec6e09c5d52069..2cbc7fde9a9383c7e8a8600adf3e83dfda01eaac 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@
 - Upgraded bundled sqlite to version 3.6.23.1. (Ilia)
 - Upgraded bundled PCRE to version 8.02. (Ilia)
 
+- Added caches to eliminate repeatable run-time bindings of functions, classes,
+  constants, methods and properties (Dmitry)
 - Added a number of small performance tweaks and optimizations (Dmitry)
   . ZEND_RECV now always has IS_CV as its result
   . ZEND_CATCH now has to be used only with constant class names
index 42b333fceb175186226510e6589249ce42fa2ab6..5f771803ccca3e461edbee2c9f45573fd3ce2493 100644 (file)
@@ -3,7 +3,6 @@ if (function_exists("date_default_timezone_set")) {
        date_default_timezone_set("UTC");
 }
 
-date_default_timezone_set('UTC');
 function simple() {
   $a = 0;
   for ($i = 0; $i < 1000000; $i++) 
index 572b64b043477045f8d0ee7f820b60a27109d792..10ef1bcea7361c1e01e712ba03bd1c0168c68189 100644 (file)
@@ -298,6 +298,7 @@ typedef struct _zend_guard {
 typedef struct _zend_object {
        zend_class_entry *ce;
        HashTable *properties;
+       zval **properties_table;
        HashTable *guards; /* protects from __get/__set ... recursion */
 } zend_object;
 
@@ -468,11 +469,13 @@ struct _zend_class_entry {
        zend_uint ce_flags;
 
        HashTable function_table;
-       HashTable default_properties;
        HashTable properties_info;
-       HashTable default_static_members;
-       HashTable *static_members;
+       zval **default_properties_table;
+       zval **default_static_members_table;
+       zval **static_members_table;
        HashTable constants_table;
+       int default_properties_count;
+       int default_static_members_count;
        const struct _zend_function_entry *builtin_functions;
 
        union _zend_function *constructor;
index e44f6f8bc9389ba6a25897dd0987a4c2aa94ee2d..567f45c03d14bf57d10e83b2925133ee0991911f 100644 (file)
@@ -1005,45 +1005,41 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro
 
 ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
 {
-       if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) {
+       if (!class_type->constants_updated || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
                zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
                zend_class_entry *old_scope = *scope;
+               int i;
 
                *scope = class_type;
                zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
-               zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
 
-               if (!CE_STATIC_MEMBERS(class_type)) {
-                       HashPosition pos;
+               for (i = 0; i < class_type->default_properties_count; i++) {
+                       if (class_type->default_properties_table[i]) {
+                               zval_update_constant(&class_type->default_properties_table[i], (void**)1 TSRMLS_CC);
+                       }
+               }
+
+               if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
                        zval **p;
 
                        if (class_type->parent) {
                                zend_update_class_constants(class_type->parent TSRMLS_CC);
                        }
 #if ZTS
-                       ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]);
+                       CG(static_members)[(zend_intptr_t)(class_type->static_members)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
 #else
-                       ALLOC_HASHTABLE(class_type->static_members);
+                       class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
 #endif
-                       zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0);
-
-                       zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
-                       while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
-                               char *str_index;
-                               uint str_length;
-                               ulong num_index;
-                               zval **q;
-
-                               zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
+                       for (i = 0; i < class_type->default_static_members_count; i++) {
+                               p = &class_type->default_static_members_table[i];
                                if (Z_ISREF_PP(p) &&
                                        class_type->parent &&
-                                       zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
-                                       *p == *q &&
-                                       zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS
+                                       class_type->parent->default_static_members_count < i &&
+                                       *p == class_type->parent->default_static_members_table[i]
                                ) {
-                                       Z_ADDREF_PP(q);
-                                       Z_SET_ISREF_PP(q);
-                                       zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL);
+                                       Z_ADDREF_PP(p);
+                                       Z_SET_ISREF_PP(p);
+                                       class_type->static_members_table[i] = *p;
                                } else {
                                        zval *r;
 
@@ -1051,12 +1047,14 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
                                        *r = **p;
                                        INIT_PZVAL(r);
                                        zval_copy_ctor(r);
-                                       zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL);
+                                       class_type->static_members_table[i] = r;
                                }
-                               zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
                        }
                }
-               zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
+
+               for (i = 0; i < class_type->default_static_members_count; i++) {
+                       zval_update_constant(&CE_STATIC_MEMBERS(class_type)[i], (void**)1 TSRMLS_CC);
+               }
 
                *scope = old_scope;
                class_type->constants_updated = 1;
@@ -1064,13 +1062,29 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
 }
 /* }}} */
 
+ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
+{
+       int i;
+
+       if (class_type->default_properties_count) {
+               object->properties_table = emalloc(sizeof(zval*) * class_type->default_properties_count);
+               for (i = 0; i < class_type->default_properties_count; i++) {
+                       object->properties_table[i] = class_type->default_properties_table[i];
+                       if (class_type->default_properties_table[i]) {
+                               Z_ADDREF_P(object->properties_table[i]);
+                       }
+               }
+               object->properties = NULL;
+       }
+}
+/* }}} */
+
 /* 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 seperately by
  * calling zend_merge_properties(). */
 ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
 {
-       zval *tmp;
        zend_object *object;
 
        if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
@@ -1085,10 +1099,9 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
                Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
                if (properties) {
                        object->properties = properties;
+                       object->properties_table = NULL;
                } else {
-                       ALLOC_HASHTABLE_REL(object->properties);
-                       zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0);
-                       zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+                       object_properties_init(object, class_type);
                }
        } else {
                Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
@@ -2315,8 +2328,6 @@ static zend_object_value display_disabled_class(zend_class_entry *class_type TSR
        zend_object_value retval;
        zend_object *intern;
        retval = zend_objects_new(&intern, class_type TSRMLS_CC);
-       ALLOC_HASHTABLE(intern->properties);
-       zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
        zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
        return retval;
 }
@@ -3076,17 +3087,38 @@ ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
 
 ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
 {
-       zend_property_info property_info;
-       HashTable *target_symbol_table;
+       zend_property_info property_info, *property_info_ptr;
        char *interned_name;
+       ulong h = zend_get_hash_value(name, name_length+1);
 
        if (!(access_type & ZEND_ACC_PPP_MASK)) {
                access_type |= ZEND_ACC_PUBLIC;
        }
        if (access_type & ZEND_ACC_STATIC) {
-               target_symbol_table = &ce->default_static_members;
+               if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
+                   (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
+                       property_info.offset = property_info_ptr->offset;
+                       zval_ptr_dtor(&ce->default_static_members_table[property_info.offset]);
+                       zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
+               } else {
+                       property_info.offset = ce->default_static_members_count++;
+                       ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
+               }
+               ce->default_static_members_table[property_info.offset] = property;
+               if (ce->type == ZEND_USER_CLASS) {
+                       ce->static_members_table = ce->default_static_members_table;
+               }
        } else {
-               target_symbol_table = &ce->default_properties;
+               if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
+                   (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
+                       property_info.offset = property_info_ptr->offset;
+                       zval_ptr_dtor(&ce->default_properties_table[property_info.offset]);
+                       zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
+               } else {
+                       property_info.offset = ce->default_properties_count++;
+                       ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
+               }
+               ce->default_properties_table[property_info.offset] = property;
        }
        if (ce->type & ZEND_INTERNAL_CLASS) {
                switch(Z_TYPE_P(property)) {
@@ -3120,14 +3152,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
                        }
                        break;
                case ZEND_ACC_PUBLIC:
-                       if (ce->parent) {
-                               char *prot_name;
-                               int prot_name_length;
-
-                               zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
-                               zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
-                               pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
-                       }
                        if (IS_INTERNED(name)) {
                                property_info.name = (char*)name;
                        } else {
@@ -3147,17 +3171,15 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in
                property_info.name = interned_name;
        }
 
-       zend_hash_update(target_symbol_table, property_info.name, property_info.name_length+1, &property, sizeof(zval *), NULL);
-
        property_info.flags = access_type;
-       property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
+       property_info.h = (access_type & ZEND_ACC_PUBLIC) ? h : zend_get_hash_value(property_info.name, property_info.name_length+1);
 
        property_info.doc_comment = doc_comment;
        property_info.doc_comment_len = doc_comment_len;
 
        property_info.ce = ce;
 
-       zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
+       zend_hash_quick_update(&ce->properties_info, name, name_length + 1, h, &property_info, sizeof(zend_property_info), NULL);
 
        return SUCCESS;
 }
index df126c806fe903641f4705af1d51aae532c4a988..e07b52f503e3a5e67fa83097292bf454bedc239b 100644 (file)
@@ -208,9 +208,9 @@ typedef struct _zend_fcall_info_cache {
        INIT_OVERLOADED_CLASS_ENTRY(class_container, ZEND_NS_NAME(ns, class_name), functions, handle_fcall, handle_propget, handle_propset)
 
 #ifdef ZTS
-#      define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members)[(zend_intptr_t)(ce)->static_members])
+#      define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members_table)[(zend_intptr_t)(ce)->static_members_table])
 #else
-#      define CE_STATIC_MEMBERS(ce) ((ce)->static_members)
+#      define CE_STATIC_MEMBERS(ce) ((ce)->static_members_table)
 #endif
 
 #define ZEND_FCI_INITIALIZED(fci) ((fci).size != 0)
@@ -347,6 +347,7 @@ ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC);
 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 zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC);
 
index 0a675bba425db126441efad65245ef2331316f86..1dbaeda04900b6d3874c70429fc0f1847d90277e 100644 (file)
@@ -888,49 +888,53 @@ ZEND_FUNCTION(is_a)
 
 
 /* {{{ add_class_vars */
-static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *return_value TSRMLS_DC)
+static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
 {
-       if (zend_hash_num_elements(properties) > 0) {
-               HashPosition pos;
-               zval **prop;
-
-               zend_hash_internal_pointer_reset_ex(properties, &pos);
-               while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
-                       char *key, *class_name, *prop_name;
-                       uint key_len;
-                       ulong num_index;
-                       int prop_name_len = 0;                  
-                       zval *prop_copy;
-                       zend_property_info *property_info;
-                       zval zprop_name;
-
-                       zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
-                       zend_hash_move_forward_ex(properties, &pos);
-
-                       zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
-                       prop_name_len = strlen(prop_name);
-
-                       ZVAL_STRINGL(&zprop_name, prop_name, prop_name_len, 0);
-                       property_info = zend_get_property_info(ce, &zprop_name, 1 TSRMLS_CC);
-
-                       if (!property_info || property_info == &EG(std_property_info)) {
-                               continue;
-                       }
+       HashPosition pos;
+       zend_property_info *prop_info;
+       zval *prop, *prop_copy;
+       char *key;
+       uint key_len;
+       ulong num_index;
 
-                       /* copy: enforce read only access */
-                       ALLOC_ZVAL(prop_copy);
-                       *prop_copy = **prop;
-                       zval_copy_ctor(prop_copy);
-                       INIT_PZVAL(prop_copy);
+       zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+       while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
+               zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
+               zend_hash_move_forward_ex(&ce->properties_info, &pos);
+               if (((prop_info->flags & ZEND_ACC_SHADOW) &&
+                    prop_info->ce != EG(scope)) ||
+                   ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+                    !zend_check_protected(prop_info->ce, EG(scope))) ||
+                   ((prop_info->flags & ZEND_ACC_PRIVATE) &&
+                     ce != EG(scope) &&
+                         prop_info->ce != EG(scope))) {
+                       continue;
+               }
+               prop = NULL;
+               if (prop_info->offset >= 0) {
+                       if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
+                               prop = ce->default_static_members_table[prop_info->offset];
+                       } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
+                               prop = ce->default_properties_table[prop_info->offset];
+                       }
+               }
+               if (!prop) {
+                       continue;
+               }
 
-                       /* this is necessary to make it able to work with default array 
-                       * properties, returned to user */
-                       if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
-                               zval_update_constant(&prop_copy, 0 TSRMLS_CC);
-                       }
+               /* copy: enforce read only access */
+               ALLOC_ZVAL(prop_copy);
+               *prop_copy = *prop;
+               zval_copy_ctor(prop_copy);
+               INIT_PZVAL(prop_copy);
 
-                       add_assoc_zval(return_value, prop_name, prop_copy);
+               /* this is necessary to make it able to work with default array
+                * properties, returned to user */
+               if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+                       zval_update_constant(&prop_copy, 0 TSRMLS_CC);
                }
+
+               add_assoc_zval(return_value, key, prop_copy);
        }
 }
 /* }}} */
@@ -953,8 +957,8 @@ ZEND_FUNCTION(get_class_vars)
        } else {
                array_init(return_value);
                zend_update_class_constants(*pce TSRMLS_CC);
-               add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC);
-               add_class_vars(*pce, CE_STATIC_MEMBERS(*pce), return_value TSRMLS_CC);
+               add_class_vars(*pce, 0, return_value TSRMLS_CC);
+               add_class_vars(*pce, 1, return_value TSRMLS_CC);
        }
 }
 /* }}} */
index a48fca7c4047c82fad968ac4f23d746170f36390..4af725eccaf6647dc25a263ddc259c2063e24c14 100644 (file)
                } \
     } while (0)
 
+#define GET_CACHE_SLOT(literal) do { \
+               CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
+       } while (0)
+
+#define POLYMORPHIC_CACHE_SLOT_SIZE 2
+
+#define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
+               CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
+               CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
+       } while (0)
+
+#define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
+               if (CG(active_op_array)->literals[literal].cache_slot == \
+                   CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
+                       CG(active_op_array)->literals[literal].cache_slot = -1; \
+                       CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
+               } \
+       } while (0)
+
 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
 ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
 
@@ -361,6 +380,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv) /* {{{ */
        Z_SET_REFCOUNT(CONSTANT_EX(op_array, i), 2);
        Z_SET_ISREF(CONSTANT_EX(op_array, i));
        op_array->literals[i].hash_value = 0;
+       op_array->literals[i].cache_slot = -1;
        return i;
 }
 /* }}} */
@@ -373,7 +393,8 @@ int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC
        int lc_literal;
 
        if (op_array->last_literal > 0 && 
-           &op_array->literals[op_array->last_literal - 1].constant == zv) {
+           &op_array->literals[op_array->last_literal - 1].constant == zv &&
+           op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
@@ -398,7 +419,8 @@ int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS
        int lc_literal;
 
        if (op_array->last_literal > 0 && 
-           &op_array->literals[op_array->last_literal - 1].constant == zv) {
+           &op_array->literals[op_array->last_literal - 1].constant == zv &&
+           op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
@@ -430,7 +452,8 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
        int lc_literal;
 
        if (op_array->last_literal > 0 && 
-           &op_array->literals[op_array->last_literal - 1].constant == zv) {
+           &op_array->literals[op_array->last_literal - 1].constant == zv &&
+           op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
@@ -448,6 +471,8 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
        lc_literal = zend_add_literal(CG(active_op_array), &c);
        CALCULATE_LITERAL_HASH(lc_literal);
 
+       GET_CACHE_SLOT(ret);
+
        return ret;
 }
 /* }}} */
@@ -460,7 +485,8 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
        zval c;
 
        if (op_array->last_literal > 0 && 
-           &op_array->literals[op_array->last_literal - 1].constant == zv) {
+           &op_array->literals[op_array->last_literal - 1].constant == zv &&
+           op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
@@ -710,6 +736,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
                opline.op1_type = IS_CONST;
                LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
                CALCULATE_LITERAL_HASH(opline.op1.constant);
+               GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
                if (class_node.op_type == IS_CONST) {
                        opline.op2_type = IS_CONST;
                        opline.op2.constant =
@@ -734,6 +761,7 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
                        opline.op1_type = IS_CONST;
                        LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
                        CALCULATE_LITERAL_HASH(opline.op1.constant);
+                       GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
                        if (class_node.op_type == IS_CONST) {
                                opline.op2_type = IS_CONST;
                                opline.op2.constant =
@@ -746,6 +774,9 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
 
                        zend_llist_prepend_element(fetch_list_ptr, &opline);
                } else {
+                       if (opline_ptr->op1_type == IS_CONST) {
+                               GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
+                       }
                        if (class_node.op_type == IS_CONST) {
                                opline_ptr->op2_type = IS_CONST;
                                opline_ptr->op2.constant =
@@ -1921,8 +1952,16 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
 
        if (last_op->opcode == ZEND_FETCH_OBJ_R) {
                if (last_op->op2_type == IS_CONST) {
+                       zval name;
+
+                       name = CONSTANT(last_op->op2.constant);
+                       if (!IS_INTERNED(Z_STRVAL(name))) {
+                               Z_STRVAL(name) = estrndup(Z_STRVAL(name), Z_STRLEN(name));
+                       }
+                       FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
                        last_op->op2.constant =
-                               zend_add_func_name_literal(CG(active_op_array), &CONSTANT(last_op->op2.constant) TSRMLS_CC);
+                               zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
+                       GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
                }
                last_op->opcode = ZEND_INIT_METHOD_CALL;
                SET_UNUSED(last_op->result);
@@ -1934,6 +1973,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
                if (left_bracket->op_type == IS_CONST) {
                        opline->op2_type = IS_CONST;
                        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
+                       GET_CACHE_SLOT(opline->op2.constant);
                } else {
                        SET_NODE(opline->op2, left_bracket);
                }
@@ -1970,12 +2010,14 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML
                SET_UNUSED(opline->op1);
                opline->op2_type = IS_CONST;
                opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
+               GET_CACHE_SLOT(opline->op2.constant);
        } else {
                opline->opcode = ZEND_INIT_FCALL_BY_NAME;
                SET_UNUSED(opline->op1);
                if (function_name->op_type == IS_CONST) {
                        opline->op2_type = IS_CONST;
                        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
+                       GET_CACHE_SLOT(opline->op2.constant);
                } else {
                        SET_NODE(opline->op2, function_name);
                }
@@ -2341,6 +2383,11 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na
                opline->op2_type = IS_CONST;
                opline->op2.constant =
                        zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
+               if (opline->op1_type == IS_CONST) {
+                       GET_CACHE_SLOT(opline->op2.constant);
+               } else {
+                       GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
+               }
        } else {
                SET_NODE(opline->op2, method_name);
        }
@@ -2367,6 +2414,7 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode
                        opline->opcode = ZEND_DO_FCALL;
                        SET_NODE(opline->op1, function_name);
                        CALCULATE_LITERAL_HASH(opline->op1.constant);
+                       GET_CACHE_SLOT(opline->op1.constant);
                } else {
                        opline->opcode = ZEND_DO_FCALL_BY_NAME;
                        SET_UNUSED(opline->op1);
@@ -2727,6 +2775,7 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
                        zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
                        zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
                }
+               op_array->run_time_cache = NULL;
        }
 }
 /* }}} */
@@ -3032,42 +3081,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
 
                if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
                        zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
-               } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
-                       if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
-                               /* Explicitly copy the default value from the parent (if it has one) */
-                               zval **pvalue;
-       
-                               if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
-                                       Z_ADDREF_PP(pvalue);
-                                       zend_hash_quick_del(&ce->default_properties, child_info->name, child_info->name_length+1, parent_info->h);
-                                       zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
-                               }
-                       }
-                       return 1; /* Inherit from the parent */
-               } else if ((child_info->flags & ZEND_ACC_PUBLIC) && (parent_info->flags & ZEND_ACC_PROTECTED)) {
-                       char *prot_name;
-                       int prot_name_length;
-
-                       zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
-                       if (child_info->flags & ZEND_ACC_STATIC) {
-                               zval **prop;
-                               HashTable *ht;
-
-                               if (parent_ce->type != ce->type) {
-                                       /* User class extends internal class */
-                                       TSRMLS_FETCH();
-
-                                       ht = CE_STATIC_MEMBERS(parent_ce);
-                               } else {
-                                       ht = &parent_ce->default_static_members;
-                               }
-                               if (zend_hash_find(ht, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
-                                       zend_hash_del(&ce->default_static_members, prot_name, prot_name_length+1);
-                               }
-                       } else {
-                               zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
-                       }
-                       pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
+               } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
+                       Z_DELREF_P(ce->default_properties_table[parent_info->offset]);
+                       ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
+                       ce->default_properties_table[child_info->offset] = NULL;
+                       child_info->offset = parent_info->offset;
                }
                return 0;       /* Don't copy from parent */
        } else {
@@ -3140,6 +3158,8 @@ static int inherit_static_prop(zval **p TSRMLS_DC, int num_args, va_list args, c
 
 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
 {
+       zend_property_info *property_info;
+
        if ((ce->ce_flags & ZEND_ACC_INTERFACE)
                && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
                zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
@@ -3161,14 +3181,78 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
        zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
 
        /* Inherit properties */
-       zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
+       if (parent_ce->default_properties_count) {
+               int i = ce->default_properties_count + parent_ce->default_properties_count;
+
+               ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
+               if (ce->default_properties_count) {
+                       while (i-- > parent_ce->default_properties_count) {
+                               ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
+                       }
+               }
+               for (i = 0; i < parent_ce->default_properties_count; i++) {
+                       ce->default_properties_table[i] = parent_ce->default_properties_table[i];
+                       if (ce->default_properties_table[i]) {
+                               Z_ADDREF_P(ce->default_properties_table[i]);
+                       }
+               }
+               ce->default_properties_count += parent_ce->default_properties_count;
+       }
+
        if (parent_ce->type != ce->type) {
                /* User class extends internal class */
                zend_update_class_constants(parent_ce  TSRMLS_CC);
-               zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
+               if (parent_ce->default_static_members_count) {
+                       int i = ce->default_static_members_count + parent_ce->default_static_members_count;
+
+                       ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
+                       if (ce->default_static_members_count) {
+                               while (i-- > parent_ce->default_static_members_count) {
+                                       ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
+                               }
+                       }
+                       for (i = 0; i < parent_ce->default_static_members_count; i++) {
+                               SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
+                               ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
+                               Z_ADDREF_P(ce->default_static_members_table[i]);
+                       }
+                       ce->default_static_members_count += parent_ce->default_static_members_count;
+                       ce->static_members_table = ce->default_static_members_table;
+               }
        } else {
-               zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
+               if (parent_ce->default_static_members_count) {
+                       int i = ce->default_static_members_count + parent_ce->default_static_members_count;
+
+                       ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
+                       if (ce->default_static_members_count) {
+                               while (i-- > parent_ce->default_static_members_count) {
+                                       ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
+                               }
+                       }
+                       for (i = 0; i < parent_ce->default_static_members_count; i++) {
+                               SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
+                               ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
+                               Z_ADDREF_P(ce->default_static_members_table[i]);
+                       }
+                       ce->default_static_members_count += parent_ce->default_static_members_count;
+                       if (ce->type == ZEND_USER_CLASS) {
+                               ce->static_members_table = ce->default_static_members_table;
+                       }
+               }
        }
+                                                                       
+       for (zend_hash_internal_pointer_reset(&ce->properties_info);
+            zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
+            zend_hash_move_forward(&ce->properties_info)) {
+               if (property_info->ce == ce) {
+                       if (property_info->flags & ZEND_ACC_STATIC) {
+                               property_info->offset += parent_ce->default_static_members_count;
+                       } else {
+                               property_info->offset += parent_ce->default_properties_count;
+                       }
+               }
+       }
+
        zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
 
        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
@@ -4651,9 +4735,7 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui
        }
 
        if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
-               if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
-                       zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
-               }
+               zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
        }
        ALLOC_ZVAL(property);
 
@@ -4748,6 +4830,7 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
                        }
                        if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
                                CALCULATE_LITERAL_HASH(opline_ptr->op2.constant);
+                               GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
                        }
                        GET_NODE(result, opline_ptr->result);
                        return;
@@ -4762,6 +4845,7 @@ void zend_do_fetch_property(znode *result, znode *object, const znode *property
        SET_NODE(opline.op2, property);
        if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
                CALCULATE_LITERAL_HASH(opline.op2.constant);
+               GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
        }
        GET_NODE(result, opline.result);
 
@@ -4931,6 +5015,11 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                                }
                                SET_NODE(opline->op2, constant_name);
                                CALCULATE_LITERAL_HASH(opline->op2.constant);
+                               if (opline->op1_type == IS_CONST) {
+                                       GET_CACHE_SLOT(opline->op2.constant);
+                               } else {
+                                       GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
+                               }
                                GET_NODE(result, opline->result);
                                break;
                }
@@ -4985,6 +5074,7 @@ void zend_do_fetch_constant(znode *result, znode *constant_container, znode *con
                                        opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
                                }
                        }
+                       GET_CACHE_SLOT(opline->op2.constant);
                        break;
        }
 }
@@ -5016,6 +5106,7 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
        LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0);
        CALCULATE_LITERAL_HASH(opline->op1.constant);
        opline->op1_type = IS_CONST;
+       GET_CACHE_SLOT(opline->op1.constant);
        opline->extended_value = 1;
        SET_UNUSED(opline->op2);
        GET_NODE(result, opline->result);
@@ -6039,9 +6130,9 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
        ce->doc_comment = NULL;
        ce->doc_comment_len = 0;
 
-       zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
+       ce->default_properties_table = NULL;
+       ce->default_static_members_table = NULL;
        zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
-       zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
        zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
        zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
 
@@ -6055,14 +6146,17 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
                        CG(static_members) = realloc(CG(static_members), (n+1)*sizeof(HashTable*));
                        CG(static_members)[n] = NULL;
                }
-               ce->static_members = (HashTable*)(zend_intptr_t)n;
+               ce->static_members_table = (zval**)(zend_intptr_t)n;
 #else
-               ce->static_members = NULL;
+               ce->static_members_table = NULL;
 #endif
        } else {
-               ce->static_members = &ce->default_static_members;
+               ce->static_members_table = &ce->default_static_members_table;
        }
 
+       ce->default_properties_count = 0;
+       ce->default_static_members_count = 0;
+
        if (nullify_handlers) {
                ce->constructor = NULL;
                ce->destructor = NULL;
index 480008ea4ca8b252c9318b93a321a392a594c33e..c22c7f979d8dc5d925f4a76e90c003098b4c0356 100644 (file)
@@ -53,8 +53,9 @@ typedef struct _zend_op_array zend_op_array;
 typedef struct _zend_op zend_op;
 
 typedef struct _zend_literal {
-       zval constant;
-       ulong hash_value;
+       zval       constant;
+       zend_ulong hash_value;
+       zend_uint  cache_slot;
 } zend_literal;
 
 #define Z_HASH_P(zv) \
@@ -183,6 +184,7 @@ typedef struct _zend_property_info {
        char *name;
        int name_length;
        ulong h;
+       int offset;
        char *doc_comment;
        int doc_comment_len;
        zend_class_entry *ce;
@@ -258,6 +260,9 @@ struct _zend_op_array {
        zend_literal *literals;
        int last_literal, size_literal;
 
+       void **run_time_cache;
+       int  last_cache_slot;
+
        void *reserved[ZEND_MAX_RESERVED_RESOURCES];
 };
 
index 301037ade5c4a672645770983f28bf50560b00a8..abed6c7f84d1e43a60f9bc8d7211ed51dce14145 100644 (file)
@@ -138,16 +138,14 @@ ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
 
 static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC) /* {{{ */
 {
-       zval tmp, obj;
+       zval obj;
        zend_object *object;
        zval *trace;
 
        Z_OBJVAL(obj) = zend_objects_new(&object, class_type TSRMLS_CC);
        Z_OBJ_HT(obj) = &default_exception_handlers;
 
-       ALLOC_HASHTABLE(object->properties);
-       zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(object, class_type);
 
        ALLOC_ZVAL(trace);
        Z_UNSET_ISREF_P(trace);
index 28e26d393249c0cb6312a460ca12886df775264a..78b79431a9d80ea85393911f67ea813a2cbb348d 100644 (file)
@@ -429,6 +429,23 @@ ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const t
 
 ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS);
 
+#define CACHED_PTR(num) \
+       EG(active_op_array)->run_time_cache[(num)]
+
+#define CACHE_PTR(num, ptr) do { \
+               EG(active_op_array)->run_time_cache[(num)] = (ptr); \
+       } while (0)
+
+#define CACHED_POLYMORPHIC_PTR(num, ce) \
+       ((EG(active_op_array)->run_time_cache[(num)] == (ce)) ? \
+               EG(active_op_array)->run_time_cache[(num) + 1] : \
+               NULL)
+
+#define CACHE_POLYMORPHIC_PTR(num, ce, ptr) do { \
+               EG(active_op_array)->run_time_cache[(num)] = (ce); \
+               EG(active_op_array)->run_time_cache[(num) + 1] = (ptr); \
+       } while (0)
+
 END_EXTERN_C()
 
 #endif /* ZEND_EXECUTE_H */
index 335d29ad7f6d80e89827c3a6e2256483aa7751ef..ef1ee3dad9ad22e42c2084bb6d909ed4fe4ffbb1 100644 (file)
@@ -32,7 +32,8 @@
 
 #define DEBUG_OBJECT_HANDLERS 0
 
-#define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p TSRMLS_CC)
+#define Z_OBJ_P(zval_p) \
+       ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object))
 
 /*
   __X accessors explanation:
   called, we cal __call handler.
 */
 
+ZEND_API void rebuild_object_properties(zend_object *zobj) /* {{{ */
+{
+       if (!zobj->properties) {
+               HashPosition pos;
+               zend_property_info *prop_info;
+               zend_class_entry *ce = zobj->ce;
+
+               ALLOC_HASHTABLE(zobj->properties);
+               zend_hash_init(zobj->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+               if (ce->default_properties_count) {
+                       for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+                            zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
+                            zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
+                               if (/*prop_info->ce == ce &&*/
+                                   (prop_info->flags & ZEND_ACC_STATIC) == 0 && 
+                                   prop_info->offset >= 0 &&
+                                   zobj->properties_table[prop_info->offset]) {
+                                       zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
+                               }                               
+                       }
+                       while (ce->parent && ce->parent->default_properties_count) {
+                               ce = ce->parent;
+                               for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+                                    zend_hash_get_current_data_ex(&ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
+                                    zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
+                                       if (prop_info->ce == ce &&
+                                           (prop_info->flags & ZEND_ACC_STATIC) == 0 && 
+                                           (prop_info->flags & ZEND_ACC_PRIVATE) != 0 && 
+                                           prop_info->offset >= 0 &&
+                                           zobj->properties_table[prop_info->offset]) {
+                                               zend_hash_quick_add(zobj->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&zobj->properties_table[prop_info->offset], sizeof(zval*), (void**)&zobj->properties_table[prop_info->offset]);
+                                       }                               
+                               }
+                       }
+               }
+       }
+}
+
+
 ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC) /* {{{ */
 {
        zend_object *zobj;
        zobj = Z_OBJ_P(object);
+       if (!zobj->properties) {
+               rebuild_object_properties(zobj);
+       }
        return zobj->properties;
 }
 /* }}} */
@@ -158,7 +201,7 @@ static zval *zend_std_call_issetter(zval *object, zval *member TSRMLS_DC) /* {{{
 }
 /* }}} */
 
-static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */
+static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) /* {{{ */
 {
        switch (property_info->flags & ZEND_ACC_PPP_MASK) {
                case ZEND_ACC_PUBLIC:
@@ -177,7 +220,7 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c
 }
 /* }}} */
 
-static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
+static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_class, zend_class_entry *parent_class) /* {{{ */
 {
        child_class = child_class->parent;
        while (child_class) {
@@ -191,13 +234,17 @@ static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_cla
 }
 /* }}} */
 
-static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */
+static zend_always_inline struct _zend_property_info *zend_get_property_info_quick(zend_class_entry *ce, zval *member, int silent, const zend_literal *key TSRMLS_DC) /* {{{ */
 {
        zend_property_info *property_info;
        zend_property_info *scope_property_info;
        zend_bool denied_access = 0;
        ulong h;
 
+       if (key && (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) != NULL) {
+               return property_info;
+       }
+
        if (UNEXPECTED(Z_STRVAL_P(member)[0] == '\0')) {
                if (!silent) {
                        if (Z_STRLEN_P(member) == 0) {
@@ -223,9 +270,12 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
                                         * continue checking below...
                                         */
                                } else {
-                                       if (!silent && (property_info->flags & ZEND_ACC_STATIC)) {
+                                       if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) != 0) && !silent) {
                                                zend_error(E_STRICT, "Accessing static property %s::$%s as non static", ce->name, Z_STRVAL_P(member));
                                        }
+                                       if (key) {
+                                               CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
+                                       }
                                        return property_info;
                                }
                        } else {
@@ -235,10 +285,13 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
                }
        }
        if (EG(scope) != ce
-               && is_derived_class(ce, EG(scope))
                && EG(scope)
+               && is_derived_class(ce, EG(scope))
                && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
                && scope_property_info->flags & ZEND_ACC_PRIVATE) {
+               if (key) {
+                       CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, scope_property_info);
+               }
                return scope_property_info;
        } else if (property_info) {
                if (UNEXPECTED(denied_access != 0)) {
@@ -249,6 +302,9 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
                        return NULL;
                } else {
                        /* fall through, return property_info... */
+                       if (key) {
+                               CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
+                       }
                }
        } else {
                EG(std_property_info).flags = ZEND_ACC_PUBLIC;
@@ -256,6 +312,7 @@ static struct _zend_property_info *zend_get_property_info_quick(zend_class_entry
                EG(std_property_info).name_length = Z_STRLEN_P(member);
                EG(std_property_info).h = h;
                EG(std_property_info).ce = ce;
+               EG(std_property_info).offset = -1;
                property_info = &EG(std_property_info);
        }
        return property_info;
@@ -348,7 +405,13 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li
        property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
 
        if (UNEXPECTED(!property_info) ||
-           UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)) {
+           ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+            property_info->offset >= 0) ?
+               (zobj->properties ?
+                   ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
+                   (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
+               (UNEXPECTED(!zobj->properties) ||
+                 UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
                zend_guard *guard;
 
                if (zobj->ce->__get &&
@@ -397,7 +460,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, const zend_li
 }
 /* }}} */
 
-static void zend_std_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
+ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) /* {{{ */
 {
        zend_object *zobj;
        zval *tmp_member = NULL;
@@ -419,7 +482,13 @@ static void zend_std_write_property(zval *object, zval *member, zval *value, con
        property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__set != NULL), key TSRMLS_CC);
 
        if (EXPECTED(property_info != NULL) &&
-           EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)) {
+           ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+            property_info->offset >= 0) ?
+               (zobj->properties ?
+                   ((variable_ptr = (zval**)zobj->properties_table[property_info->offset]) != NULL) :
+                   (*(variable_ptr = &zobj->properties_table[property_info->offset]) != NULL)) :
+               (EXPECTED(zobj->properties != NULL) &&
+                 EXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS)))) {
                /* if we already have this value there, we don't actually need to do anything */
                if (EXPECTED(*variable_ptr != value)) {
                        /* if we are assigning reference, we shouldn't move it, but instead assign variable
@@ -462,15 +531,27 @@ static void zend_std_write_property(zval *object, zval *member, zval *value, con
                        guard->in_set = 0;
                        zval_ptr_dtor(&object);
                }
-               if (!setter_done && property_info) {
-                       zval **foo;
-
+               if (!setter_done && EXPECTED(property_info != NULL)) {
                        /* if we assign referenced variable, we should separate it */
                        Z_ADDREF_P(value);
                        if (PZVAL_IS_REF(value)) {
                                SEPARATE_ZVAL(&value);
                        }
-                       zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
+                       if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+                           property_info->offset >= 0) {
+                               if (!zobj->properties) {
+                                       zobj->properties_table[property_info->offset] = value;
+                               } else if (zobj->properties_table[property_info->offset]) {
+                                       *(zval**)zobj->properties_table[property_info->offset] = value;
+                               } else {
+                                       zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
+                               }
+                       } else {
+                               if (!zobj->properties) {
+                                       rebuild_object_properties(zobj);
+                               }
+                               zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), NULL);
+                       }
                }
        }
 
@@ -587,7 +668,13 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze
        property_info = zend_get_property_info_quick(zobj->ce, member, (zobj->ce->__get != NULL), key TSRMLS_CC);
 
        if (UNEXPECTED(!property_info) ||
-           UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)) {
+           ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+            property_info->offset >= 0) ?
+               (zobj->properties ?
+                   ((retval = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
+                   (*(retval = &zobj->properties_table[property_info->offset]) == NULL)) :
+               (UNEXPECTED(!zobj->properties) ||
+                 UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE)))) {
                zval *new_zval;
                zend_guard *guard;
 
@@ -599,7 +686,24 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member, const ze
 
 /*                     zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */
                        Z_ADDREF_P(new_zval);
-                       zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
+                       if (EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+                           property_info->offset >= 0) {
+                               if (!zobj->properties) {
+                                       zobj->properties_table[property_info->offset] = new_zval;
+                                       retval = &zobj->properties_table[property_info->offset];
+                               } else if (zobj->properties_table[property_info->offset]) {
+                                       *(zval**)zobj->properties_table[property_info->offset] = new_zval;
+                                       retval = (zval**)zobj->properties_table[property_info->offset];
+                               } else {
+                                       zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void**)&zobj->properties_table[property_info->offset]);
+                                       retval = (zval**)zobj->properties_table[property_info->offset];
+                               }
+                       } else {
+                               if (!zobj->properties) {
+                                       rebuild_object_properties(zobj);
+                               }
+                               zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
+                       }
                } else {
                        /* we do have getter - fail and let it try again with usual get/set */
                        retval = NULL;
@@ -632,8 +736,16 @@ 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 (UNEXPECTED(!property_info) ||
-           UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) {
+       if (EXPECTED(property_info != NULL) &&
+           EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && 
+           !zobj->properties &&
+           property_info->offset >= 0 &&
+           EXPECTED(zobj->properties_table[property_info->offset] != NULL)) {
+               zval_ptr_dtor(&zobj->properties_table[property_info->offset]);
+               zobj->properties_table[property_info->offset] = NULL;
+       } else if (UNEXPECTED(!property_info) ||
+                  !zobj->properties ||
+                  UNEXPECTED(zend_hash_quick_del(zobj->properties, property_info->name, property_info->name_length+1, property_info->h) == FAILURE)) {
                zend_guard *guard;
 
                if (zobj->ce->__unset &&
@@ -646,6 +758,10 @@ static void zend_std_unset_property(zval *object, zval *member, const zend_liter
                        guard->in_unset = 0;
                        zval_ptr_dtor(&object);
                }
+       } else if (EXPECTED(property_info != NULL) && 
+                  EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) && 
+                  property_info->offset >= 0) {
+               zobj->properties_table[property_info->offset] = NULL;
        }
 
        if (UNEXPECTED(tmp_member != NULL)) {
@@ -1049,50 +1165,50 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
 
 ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, zend_bool silent, const zend_literal *key TSRMLS_DC) /* {{{ */
 {
-       zval **retval = NULL;
-       zend_class_entry *tmp_ce = ce;
        zend_property_info *property_info;
-       zend_property_info std_property_info;
        ulong hash_value;
        
-       if (EXPECTED(key != NULL)) {
-               hash_value = key->hash_value;
-       } else {
-               hash_value = zend_hash_func(property_name, property_name_len+1);
-       }
+       if (UNEXPECTED(!key) ||
+           (property_info = CACHED_POLYMORPHIC_PTR(key->cache_slot, ce)) == NULL) {
+               if (EXPECTED(key != NULL)) {
+                       hash_value = key->hash_value;
+               } else {
+                       hash_value = zend_hash_func(property_name, property_name_len+1);
+               }
 
-       if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) {
-               std_property_info.flags = ZEND_ACC_PUBLIC;
-               std_property_info.name = property_name;
-               std_property_info.name_length = property_name_len;
-               std_property_info.h = hash_value;
-               std_property_info.ce = ce;
-               property_info = &std_property_info;
-       }
+               if (UNEXPECTED(zend_hash_quick_find(&ce->properties_info, property_name, property_name_len+1, hash_value, (void **) &property_info)==FAILURE)) {
+                       if (!silent) {
+                               zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+                       }
+                       return NULL;
+               }
 
 #if DEBUG_OBJECT_HANDLERS
-       zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
+               zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
 #endif
 
-       if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) {
-               if (!silent) {
-                       zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
+               if (UNEXPECTED(!zend_verify_property_access(property_info, ce TSRMLS_CC))) {
+                       if (!silent) {
+                               zend_error_noreturn(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
+                       }
+                       return NULL;
                }
-               return NULL;
-       }
 
-       zend_update_class_constants(tmp_ce TSRMLS_CC);
+               if (UNEXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0)) {
+                       if (!silent) {
+                               zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+                       }
+                       return NULL;
+               }
 
-       zend_hash_quick_find(CE_STATIC_MEMBERS(tmp_ce), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
+               zend_update_class_constants(ce TSRMLS_CC);
 
-       if (UNEXPECTED(!retval)) {
-               if (!silent) {
-                       zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+               if (EXPECTED(key != NULL)) {
+                       CACHE_POLYMORPHIC_PTR(key->cache_slot, ce, property_info);
                }
-               return NULL;
        }
 
-       return retval;
+       return &CE_STATIC_MEMBERS(ce)[property_info->offset];
 }
 /* }}} */
 
@@ -1152,7 +1268,40 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
        if (zobj1->ce != zobj2->ce) {
                return 1; /* different classes */
        }
-       return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
+       if (!zobj1->properties && !zobj2->properties) {
+               int i;
+               for (i = 0; i < zobj1->ce->default_properties_count; i++) {
+                       if (zobj1->properties_table[i]) {
+                               if (zobj2->properties_table[i]) {
+                                       zval result;
+
+                                       if (compare_function(&result, zobj1->properties_table[i], zobj2->properties_table[i] TSRMLS_CC)==FAILURE) {
+                                               return 1;
+                                       }
+                                       if (Z_LVAL(result) != 0) {
+                                               return Z_LVAL(result);
+                                       }
+                               } else {
+                                       return 1;
+                               }
+                       } else {
+                               if (zobj2->properties_table[i]) {
+                                       return 1;
+                               } else {
+                                       return 0;
+                               }
+                       }
+               }
+               return 0;
+       } else {
+               if (!zobj1->properties) {
+                       rebuild_object_properties(zobj1);
+               }
+               if (!zobj2->properties) {
+                       rebuild_object_properties(zobj2);
+               }
+               return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC);
+       }
 }
 /* }}} */
 
@@ -1160,7 +1309,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
 {
        zend_object *zobj;
        int result;
-       zval **value;
+       zval **value = NULL;
        zval *tmp_member = NULL;
        zend_property_info *property_info;
 
@@ -1183,7 +1332,13 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
        property_info = zend_get_property_info_quick(zobj->ce, member, 1, key TSRMLS_CC);
 
        if (UNEXPECTED(!property_info) ||
-           zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
+           ((EXPECTED((property_info->flags & ZEND_ACC_STATIC) == 0) &&
+            property_info->offset >= 0) ?
+               (zobj->properties ?
+                   ((value = (zval**)zobj->properties_table[property_info->offset]) == NULL) :
+                   (*(value = &zobj->properties_table[property_info->offset]) == NULL)) :
+               (UNEXPECTED(!zobj->properties) ||
+                 UNEXPECTED(zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE)))) {
                zend_guard *guard;
 
                result = 0;
index 611ba87f7d2b87f7dc5559346620574b7e96259d..542d163e23bb85cbcd34afc0bad253eb38764784 100644 (file)
@@ -152,6 +152,8 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
 ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
 ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp TSRMLS_DC);
 ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
+ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, const struct _zend_literal *key TSRMLS_DC);
+ZEND_API void rebuild_object_properties(zend_object *zobj);
 
 
 #define IS_ZEND_STD_OBJECT(z)  (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL))
index a2f1d3287e00704c2091f65d84eaef29ddf81ac1..6a87284cede1e19c1f3452649fb76d5f0a1067d3 100644 (file)
 
 ZEND_API void zend_object_std_init(zend_object *object, zend_class_entry *ce TSRMLS_DC)
 {
-       ALLOC_HASHTABLE(object->properties);
-       zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-
        object->ce = ce;        
+       object->properties = NULL;
+       object->properties_table = NULL;
        object->guards = NULL;
 }
 
@@ -44,6 +43,18 @@ ZEND_API void zend_object_std_dtor(zend_object *object TSRMLS_DC)
        if (object->properties) {
                zend_hash_destroy(object->properties);
                FREE_HASHTABLE(object->properties);
+               if (object->properties_table) {
+                       efree(object->properties_table);
+               }
+       } else if (object->properties_table) {
+               int i;
+
+               for (i = 0; i < object->ce->default_properties_count; i++) {
+                       if (object->properties_table[i]) {
+                               zval_ptr_dtor(&object->properties_table[i]);
+                       }
+               }
+               efree(object->properties_table);
        }
 }
 
@@ -135,9 +146,11 @@ ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_ent
 
        *object = emalloc(sizeof(zend_object));
        (*object)->ce = class_type;
+       (*object)->properties = NULL;
+       (*object)->properties_table = NULL;
+       (*object)->guards = NULL;
        retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) zend_objects_free_object_storage, NULL TSRMLS_CC);
        retval.handlers = &std_object_handlers;
-       (*object)->guards = NULL;
        return retval;
 }
 
@@ -148,7 +161,47 @@ ZEND_API zend_object *zend_objects_get_address(const zval *zobject TSRMLS_DC)
 
 ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object_value new_obj_val, zend_object *old_object, zend_object_handle handle TSRMLS_DC)
 {
-       zend_hash_copy(new_object->properties, old_object->properties, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
+       int i;
+
+       if (old_object->properties_table) {
+               if (!new_object->properties_table) {
+                       new_object->properties_table = emalloc(sizeof(zval*) * old_object->ce->default_properties_count);
+                       memset(new_object->properties_table, 0, sizeof(zval*) * old_object->ce->default_properties_count);
+               }
+               for (i = 0; i < old_object->ce->default_properties_count; i++) {
+                       if (!new_object->properties) {
+                               if (new_object->properties_table[i]) {
+                                       zval_ptr_dtor(&new_object->properties_table[i]);
+                               }
+                       }
+                       if (!old_object->properties) {
+                               new_object->properties_table[i] = old_object->properties_table[i];
+                               if (new_object->properties_table[i]) {
+                                       Z_ADDREF_P(new_object->properties_table[i]);
+                               }
+                       }
+               }
+       }
+       if (old_object->properties) {
+               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, (copy_ctor_func_t) zval_add_ref, (void *) NULL /* Not used anymore */, sizeof(zval *));
+               if (old_object->properties_table) {
+                       HashPosition pos;
+                       zend_property_info *prop_info;
+                       for (zend_hash_internal_pointer_reset_ex(&old_object->ce->properties_info, &pos);
+                            zend_hash_get_current_data_ex(&old_object->ce->properties_info, (void**)&prop_info, &pos) == SUCCESS;
+                            zend_hash_move_forward_ex(&old_object->ce->properties_info, &pos)) {
+                               if ((prop_info->flags & ZEND_ACC_STATIC) == 0) {
+                                       if (zend_hash_quick_find(new_object->properties, prop_info->name, prop_info->name_length+1, prop_info->h, (void**)&new_object->properties_table[prop_info->offset]) == FAILURE) {
+                                               new_object->properties_table[prop_info->offset] = NULL;
+                                       }
+                               }
+                       }
+               }
+       }
 
        if (old_object->ce->clone) {
                zval *new_obj;
@@ -176,9 +229,6 @@ ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
        old_object = zend_objects_get_address(zobject TSRMLS_CC);
        new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
 
-       ALLOC_HASHTABLE(new_object->properties);
-       zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-
        zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
 
        return new_obj_val;
index 11a846b5fff4ccc852c501d13dec50d6080a279e..880be865a548b0efffce293fb57663e1d8320239 100644 (file)
@@ -107,6 +107,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
        op_array->last_literal = 0;
        op_array->literals = NULL;
 
+       op_array->run_time_cache = NULL;
+       op_array->last_cache_slot = 0;
+
        memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
 
        zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC);
@@ -163,14 +166,18 @@ ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
                /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
                   not contain objects and thus are not probelmatic */
                zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC);
-               (*pce)->static_members = NULL;
+               (*pce)->static_members_table = NULL;
        } else if (CE_STATIC_MEMBERS(*pce)) {
-               zend_hash_destroy(CE_STATIC_MEMBERS(*pce));
-               FREE_HASHTABLE(CE_STATIC_MEMBERS(*pce));
+               int i;
+               
+               for (i = 0; i < (*pce)->default_static_members_count; i++) {
+                       zval_ptr_dtor(&CE_STATIC_MEMBERS(*pce)[i]);
+               }
+               efree(CE_STATIC_MEMBERS(*pce));
 #ifdef ZTS
                CG(static_members)[(zend_intptr_t)((*pce)->static_members)] = NULL;
 #else
-               (*pce)->static_members = NULL;
+               (*pce)->static_members_table = NULL;
 #endif
        }
        return 0;
@@ -234,9 +241,25 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
        }
        switch (ce->type) {
                case ZEND_USER_CLASS:
-                       zend_hash_destroy(&ce->default_properties);
+                       if (ce->default_properties_table) {
+                               int i;
+
+                               for (i = 0; i < ce->default_properties_count; i++) {
+                                       if (ce->default_properties_table[i]) {
+                                               zval_ptr_dtor(&ce->default_properties_table[i]);
+                                   }
+                               }
+                               efree(ce->default_properties_table);
+                       }
+                       if (ce->default_static_members_table) {
+                               int i;
+
+                               for (i = 0; i < ce->default_static_members_count; i++) {
+                                       zval_ptr_dtor(&ce->default_static_members_table[i]);
+                               }
+                               efree(ce->default_static_members_table);
+                       }
                        zend_hash_destroy(&ce->properties_info);
-                       zend_hash_destroy(&ce->default_static_members);
                        efree(ce->name);
                        zend_hash_destroy(&ce->function_table);
                        zend_hash_destroy(&ce->constants_table);
@@ -252,9 +275,25 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        efree(ce);
                        break;
                case ZEND_INTERNAL_CLASS:
-                       zend_hash_destroy(&ce->default_properties);
+                       if (ce->default_properties_table) {
+                               int i;
+
+                               for (i = 0; i < ce->default_properties_count; i++) {
+                                       if (ce->default_properties_table[i]) {
+                                               zval_internal_ptr_dtor(&ce->default_properties_table[i]);
+                                       }
+                               }
+                               free(ce->default_properties_table);
+                       }
+                       if (ce->default_static_members_table) {
+                               int i;
+
+                               for (i = 0; i < ce->default_static_members_count; i++) {
+                                       zval_internal_ptr_dtor(&ce->default_static_members_table[i]);
+                               }
+                               free(ce->default_static_members_table);
+                       }
                        zend_hash_destroy(&ce->properties_info);
-                       zend_hash_destroy(&ce->default_static_members);
                        free(ce->name);
                        zend_hash_destroy(&ce->function_table);
                        zend_hash_destroy(&ce->constants_table);
@@ -285,6 +324,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
                FREE_HASHTABLE(op_array->static_variables);
        }
 
+       if (op_array->run_time_cache) {
+               efree(op_array->run_time_cache);
+       }
+
        if (--(*op_array->refcount)>0) {
                return;
        }
index d13b3b281a52023178c20716b45e1a3e4bd20ead..5dfcaa0555aabee0d7c1fb1db05b6a189c55f8a5 100644 (file)
@@ -1035,7 +1035,12 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, UNUSED|CONST|
                zend_class_entry *ce;
 
                if (OP2_TYPE == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -2145,7 +2150,12 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV)
                zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
                if (OP2_TYPE == IS_CONST) {
-                       EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+                       }
                } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
                        EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
                } else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -2185,17 +2195,27 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
+       
+               if (OP2_TYPE != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (OP2_TYPE == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
                }
-               
-               EX(called_scope) = Z_OBJCE_P(EX(object));
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -2232,21 +2252,35 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
 
        if (OP1_TYPE == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
                ce = EX_T(opline->op1.var).class_entry;
-               
+
                if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) {
                        EX(called_scope) = EG(called_scope);
                } else {
                        EX(called_scope) = ce;
                }
        }
-       if(OP2_TYPE != IS_UNUSED) {
+
+       if (OP1_TYPE == IS_CONST &&
+           OP2_TYPE == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (OP1_TYPE != IS_CONST &&
+                  OP2_TYPE == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (OP2_TYPE != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
                zend_free_op free_op2;
@@ -2274,8 +2308,14 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (OP2_TYPE == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (OP1_TYPE == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (OP2_TYPE != IS_CONST) {
                        FREE_OP2();
                }
@@ -2322,9 +2362,13 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
 
        if (OP2_TYPE == IS_CONST) {
                function_name = (zval*)(opline->op2.literal+1);
-               if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
                EX(object) = NULL;
                /*CHECK_EXCEPTION();*/
@@ -2379,12 +2423,18 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        func_name = opline->op2.literal + 1;
-       if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
+       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
                func_name++;
                if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
+       } else {
+               CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
        }
 
        EX(object) = NULL;
@@ -2694,9 +2744,13 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
-       if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
+       if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+               EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot);
+       } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
            SAVE_OPLINE();
                zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
+       } else {
+               CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function);
        }
        EX(object) = NULL;
 
@@ -2849,7 +2903,12 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
                ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
                ZEND_VM_CONTINUE(); /* CHECK_ME */
        }
-       catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
+       if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+               catch_ce = CACHED_PTR(opline->op1.literal->cache_slot);
+       } else {
+               catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
+               CACHE_PTR(opline->op1.literal->cache_slot, catch_ce);
+       }
        ce = Z_OBJCE_P(EG(exception));
 
 #ifdef HAVE_DTRACE
@@ -3339,7 +3398,9 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
                zend_constant *c;
                zval *retval;
 
-               if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       c = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
                        if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
                                char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
                                if(!actual) {
@@ -3355,6 +3416,8 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
                        } else {
                                zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
                        }
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, c);
                }
                retval = &EX_T(opline->result.var).tmp_var;
                INIT_PZVAL_COPY(retval, &c->value);
@@ -3367,13 +3430,29 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
                zval **value;
 
                if (OP1_TYPE == IS_CONST) {
-
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-                       if (UNEXPECTED(ce == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               value = CACHED_PTR(opline->op2.literal->cache_slot);
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op1.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                               if (UNEXPECTED(ce == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                               }
+                               CACHE_PTR(opline->op1.literal->cache_slot, ce);
                        }
                } else {
                        ce = EX_T(opline->op1.var).class_entry;
+                       if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
                }
 
                if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
@@ -3385,6 +3464,11 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
                                zval_update_constant(value, (void *) 1 TSRMLS_CC);
                                EG(scope) = old_scope;
                        }
+                       if (OP1_TYPE == IS_CONST) {
+                               CACHE_PTR(opline->op2.literal->cache_slot, value);
+                       } else {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+                       }
                        ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
                        zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
                } else {
@@ -3727,7 +3811,12 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
                zend_class_entry *ce;
 
                if (OP2_TYPE == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -4227,7 +4316,12 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
                        zend_class_entry *ce;
 
                        if (OP2_TYPE == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -4654,14 +4748,21 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST)
        zend_class_entry *iface;
 
        SAVE_OPLINE();
-       iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
-
-       if (iface) {
-               if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
-                       zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+               iface = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else {
+               iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+               if (UNEXPECTED(iface == NULL)) {
+                       CHECK_EXCEPTION();
+                       ZEND_VM_NEXT_OPCODE();
                }
-               zend_do_implement_interface(ce, iface TSRMLS_CC);
+               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+       }
+
+       if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
+               zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
        }
+       zend_do_implement_interface(ce, iface TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -4671,18 +4772,27 @@ ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY)
 {
        zend_op *opline = EX(opline);
        zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
-       zend_class_entry *trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
-                                             Z_STRLEN_P(opline->op2.zv),
-                                             opline->op2.literal + 1,
-                                             opline->extended_value TSRMLS_CC);
-       
-       if (trait) {
+       zend_class_entry *trait;
+
+       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+               trait = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else {
+               trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
+                                                Z_STRLEN_P(opline->op2.zv),
+                                                opline->op2.literal + 1,
+                                                opline->extended_value TSRMLS_CC);
+               if (UNEXPECTED(trait == NULL)) {
+                       CHECK_EXCEPTION();
+                       ZEND_VM_NEXT_OPCODE();
+               }
                if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
                        zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
                }
-               zend_do_implement_trait(ce, trait TSRMLS_CC);
+               CACHE_PTR(opline->op2.literal->cache_slot, trait);
        }
 
+       zend_do_implement_trait(ce, trait TSRMLS_CC);
+
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
index f9370750f7485faf87fd42c28843ea954ad6afe5..7254fc3933dedb4e74c89bf218b4356f19175da9 100644 (file)
@@ -99,6 +99,10 @@ zend_vm_enter:
 
        LOAD_REGS();
 
+       if (!op_array->run_time_cache && op_array->last_cache_slot) {
+               op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
+       }
+
        if (op_array->this_var != -1 && EG(This)) {
                Z_ADDREF_P(EG(This)); /* For $this pointer */
                if (!EG(active_symbol_table)) {
@@ -684,18 +688,27 @@ static int ZEND_FASTCALL  ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_class_entry *ce = EX_T(opline->op1.var).class_entry;
-       zend_class_entry *trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
-                                             Z_STRLEN_P(opline->op2.zv),
-                                             opline->op2.literal + 1,
-                                             opline->extended_value TSRMLS_CC);
+       zend_class_entry *trait;
 
-       if (trait) {
+       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+               trait = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else {
+               trait = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv),
+                                                Z_STRLEN_P(opline->op2.zv),
+                                                opline->op2.literal + 1,
+                                                opline->extended_value TSRMLS_CC);
+               if (UNEXPECTED(trait == NULL)) {
+                       CHECK_EXCEPTION();
+                       ZEND_VM_NEXT_OPCODE();
+               }
                if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
                        zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name, trait->name);
                }
-               zend_do_implement_trait(ce, trait TSRMLS_CC);
+               CACHE_PTR(opline->op2.literal->cache_slot, trait);
        }
 
+       zend_do_implement_trait(ce, trait TSRMLS_CC);
+
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
 }
@@ -850,7 +863,12 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLE
                zval *class_name = opline->op2.zv;
 
                if (IS_CONST == IS_CONST) {
-                       EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+                       }
                } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
                        EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
                } else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -872,9 +890,13 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE
 
        if (IS_CONST == IS_CONST) {
                function_name = (zval*)(opline->op2.literal+1);
-               if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
                EX(object) = NULL;
                /*CHECK_EXCEPTION();*/
@@ -929,12 +951,18 @@ static int ZEND_FASTCALL  ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
        func_name = opline->op2.literal + 1;
-       if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
+       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) {
                func_name++;
                if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
+       } else {
+               CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
        }
 
        EX(object) = NULL;
@@ -1035,14 +1063,21 @@ static int ZEND_FASTCALL  ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
        zend_class_entry *iface;
 
        SAVE_OPLINE();
-       iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
-
-       if (iface) {
-               if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
-                       zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+               iface = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else {
+               iface = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+               if (UNEXPECTED(iface == NULL)) {
+                       CHECK_EXCEPTION();
+                       ZEND_VM_NEXT_OPCODE();
                }
-               zend_do_implement_interface(ce, iface TSRMLS_CC);
+               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+       }
+
+       if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
+               zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
        }
+       zend_do_implement_interface(ce, iface TSRMLS_CC);
 
        CHECK_EXCEPTION();
        ZEND_VM_NEXT_OPCODE();
@@ -1063,7 +1098,12 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
                zval *class_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
 
                if (IS_TMP_VAR == IS_CONST) {
-                       EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+                       }
                } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
                        EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
                } else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -1086,9 +1126,13 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H
 
        if (IS_TMP_VAR == IS_CONST) {
                function_name = (zval*)(opline->op2.literal+1);
-               if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
                EX(object) = NULL;
                /*CHECK_EXCEPTION();*/
@@ -1176,7 +1220,12 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_
                zval *class_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC);
 
                if (IS_VAR == IS_CONST) {
-                       EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+                       }
                } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
                        EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
                } else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -1199,9 +1248,13 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H
 
        if (IS_VAR == IS_CONST) {
                function_name = (zval*)(opline->op2.literal+1);
-               if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
                EX(object) = NULL;
                /*CHECK_EXCEPTION();*/
@@ -1289,7 +1342,12 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDL
                zval *class_name = NULL;
 
                if (IS_UNUSED == IS_CONST) {
-                       EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+                       }
                } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
                        EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
                } else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -1318,7 +1376,12 @@ static int ZEND_FASTCALL  ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A
                zval *class_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC);
 
                if (IS_CV == IS_CONST) {
-                       EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               EX_T(opline->result.var).class_entry = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               EX_T(opline->result.var).class_entry = zend_fetch_class_by_name(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->op2.literal + 1, opline->extended_value TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, EX_T(opline->result.var).class_entry);
+                       }
                } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
                        EX_T(opline->result.var).class_entry = Z_OBJCE_P(class_name);
                } else if (Z_TYPE_P(class_name) == IS_STRING) {
@@ -1340,9 +1403,13 @@ static int ZEND_FASTCALL  ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA
 
        if (IS_CV == IS_CONST) {
                function_name = (zval*)(opline->op2.literal+1);
-               if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) {
                        SAVE_OPLINE();
                        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv));
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
                }
                EX(object) = NULL;
                /*CHECK_EXCEPTION();*/
@@ -1637,9 +1704,13 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
 
        zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
 
-       if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
+       if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+               EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot);
+       } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(fname), Z_STRLEN_P(fname)+1, Z_HASH_P(fname), (void **) &EX(function_state).function)==FAILURE)) {
            SAVE_OPLINE();
                zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
+       } else {
+               CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function);
        }
        EX(object) = NULL;
 
@@ -2607,7 +2678,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -2771,9 +2847,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
 
        if (IS_CONST == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -2785,7 +2866,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
                        EX(called_scope) = ce;
                }
        }
-       if(IS_CONST != IS_UNUSED) {
+
+       if (IS_CONST == IS_CONST &&
+           IS_CONST == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_CONST != IS_CONST &&
+                  IS_CONST == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_CONST != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
 
@@ -2813,8 +2903,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_CONST == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_CONST == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_CONST != IS_CONST) {
 
                }
@@ -2895,7 +2991,9 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
                zend_constant *c;
                zval *retval;
 
-               if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       c = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
                        if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
                                char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
                                if(!actual) {
@@ -2911,6 +3009,8 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
                        } else {
                                zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
                        }
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, c);
                }
                retval = &EX_T(opline->result.var).tmp_var;
                INIT_PZVAL_COPY(retval, &c->value);
@@ -2923,13 +3023,29 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
                zval **value;
 
                if (IS_CONST == IS_CONST) {
-
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-                       if (UNEXPECTED(ce == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               value = CACHED_PTR(opline->op2.literal->cache_slot);
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op1.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                               if (UNEXPECTED(ce == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                               }
+                               CACHE_PTR(opline->op1.literal->cache_slot, ce);
                        }
                } else {
                        ce = EX_T(opline->op1.var).class_entry;
+                       if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
                }
 
                if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
@@ -2941,6 +3057,11 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
                                zval_update_constant(value, (void *) 1 TSRMLS_CC);
                                EG(scope) = old_scope;
                        }
+                       if (IS_CONST == IS_CONST) {
+                               CACHE_PTR(opline->op2.literal->cache_slot, value);
+                       } else {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+                       }
                        ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
                        zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
                } else {
@@ -3087,7 +3208,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HA
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -3144,7 +3270,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O
                        zend_class_entry *ce;
 
                        if (IS_CONST == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -3514,9 +3645,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
 
        if (IS_CONST == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -3528,7 +3664,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
                        EX(called_scope) = ce;
                }
        }
-       if(IS_TMP_VAR != IS_UNUSED) {
+
+       if (IS_CONST == IS_CONST &&
+           IS_TMP_VAR == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_CONST != IS_CONST &&
+                  IS_TMP_VAR == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_TMP_VAR != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
                zend_free_op free_op2;
@@ -3556,8 +3701,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_TMP_VAR == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_CONST == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_TMP_VAR != IS_CONST) {
                        zval_dtor(free_op2.var);
                }
@@ -4032,7 +4183,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type,
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -4170,9 +4326,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
 
        if (IS_CONST == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -4184,7 +4345,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
                        EX(called_scope) = ce;
                }
        }
-       if(IS_VAR != IS_UNUSED) {
+
+       if (IS_CONST == IS_CONST &&
+           IS_VAR == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_CONST != IS_CONST &&
+                  IS_VAR == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_VAR != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
                zend_free_op free_op2;
@@ -4212,8 +4382,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_VAR == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_CONST == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_VAR != IS_CONST) {
                        if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
                }
@@ -4421,7 +4597,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAND
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -4478,7 +4659,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC
                        zend_class_entry *ce;
 
                        if (IS_VAR == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -4541,7 +4727,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int typ
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -4679,9 +4870,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
 
        if (IS_CONST == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -4693,7 +4889,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
                        EX(called_scope) = ce;
                }
        }
-       if(IS_UNUSED != IS_UNUSED) {
+
+       if (IS_CONST == IS_CONST &&
+           IS_UNUSED == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_CONST != IS_CONST &&
+                  IS_UNUSED == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_UNUSED != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
 
@@ -4721,8 +4926,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_UNUSED == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_CONST == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_UNUSED != IS_CONST) {
 
                }
@@ -4896,7 +5107,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_H
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -4953,7 +5169,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_
                        zend_class_entry *ce;
 
                        if (IS_UNUSED == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -5301,9 +5522,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
 
        if (IS_CONST == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -5315,7 +5541,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
                        EX(called_scope) = ce;
                }
        }
-       if(IS_CV != IS_UNUSED) {
+
+       if (IS_CONST == IS_CONST &&
+           IS_CV == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_CONST != IS_CONST &&
+                  IS_CV == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_CV != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
 
@@ -5343,8 +5578,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_CV == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_CONST == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_CV != IS_CONST) {
 
                }
@@ -5395,7 +5636,12 @@ static int ZEND_FASTCALL  ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A
                ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
                ZEND_VM_CONTINUE(); /* CHECK_ME */
        }
-       catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
+       if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+               catch_ce = CACHED_PTR(opline->op1.literal->cache_slot);
+       } else {
+               catch_ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC);
+               CACHE_PTR(opline->op1.literal->cache_slot, catch_ce);
+       }
        ce = Z_OBJCE_P(EG(exception));
 
 #ifdef HAVE_DTRACE
@@ -6790,7 +7036,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type,
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -7014,17 +7265,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CONST != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CONST == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -7216,7 +7477,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -7273,7 +7539,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
                        zend_class_entry *ce;
 
                        if (IS_CONST == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -7662,17 +7933,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_TMP_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_TMP_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -8133,7 +8414,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -8330,17 +8616,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -8534,7 +8830,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -8591,7 +8892,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD
                        zend_class_entry *ce;
 
                        if (IS_VAR == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -8654,7 +8960,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type,
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -8916,7 +9227,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -8973,7 +9289,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP
                        zend_class_entry *ce;
 
                        if (IS_UNUSED == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -9361,17 +9682,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CV != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CV == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -11648,7 +11979,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type,
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -12401,17 +12737,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CONST != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CONST == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -12447,9 +12793,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
 
        if (IS_VAR == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -12461,7 +12812,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
                        EX(called_scope) = ce;
                }
        }
-       if(IS_CONST != IS_UNUSED) {
+
+       if (IS_VAR == IS_CONST &&
+           IS_CONST == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_VAR != IS_CONST &&
+                  IS_CONST == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_CONST != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
 
@@ -12489,8 +12849,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_CONST == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_VAR == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_CONST != IS_CONST) {
 
                }
@@ -12571,7 +12937,9 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
                zend_constant *c;
                zval *retval;
 
-               if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       c = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
                        if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
                                char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
                                if(!actual) {
@@ -12587,6 +12955,8 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
                        } else {
                                zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
                        }
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, c);
                }
                retval = &EX_T(opline->result.var).tmp_var;
                INIT_PZVAL_COPY(retval, &c->value);
@@ -12599,13 +12969,29 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
                zval **value;
 
                if (IS_VAR == IS_CONST) {
-
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-                       if (UNEXPECTED(ce == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               value = CACHED_PTR(opline->op2.literal->cache_slot);
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op1.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                               if (UNEXPECTED(ce == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                               }
+                               CACHE_PTR(opline->op1.literal->cache_slot, ce);
                        }
                } else {
                        ce = EX_T(opline->op1.var).class_entry;
+                       if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
                }
 
                if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
@@ -12617,6 +13003,11 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
                                zval_update_constant(value, (void *) 1 TSRMLS_CC);
                                EG(scope) = old_scope;
                        }
+                       if (IS_VAR == IS_CONST) {
+                               CACHE_PTR(opline->op2.literal->cache_slot, value);
+                       } else {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+                       }
                        ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
                        zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
                } else {
@@ -12763,7 +13154,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -12956,7 +13352,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC
                        zend_class_entry *ce;
 
                        if (IS_CONST == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -14516,17 +14917,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_TMP_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_TMP_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -14563,9 +14974,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
 
        if (IS_VAR == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -14577,7 +14993,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
                        EX(called_scope) = ce;
                }
        }
-       if(IS_TMP_VAR != IS_UNUSED) {
+
+       if (IS_VAR == IS_CONST &&
+           IS_TMP_VAR == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_VAR != IS_CONST &&
+                  IS_TMP_VAR == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_TMP_VAR != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
                zend_free_op free_op2;
@@ -14605,8 +15030,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_TMP_VAR == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_VAR == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_TMP_VAR != IS_CONST) {
                        zval_dtor(free_op2.var);
                }
@@ -15831,7 +16262,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -16640,17 +17076,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -16687,9 +17133,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
 
        if (IS_VAR == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -16701,7 +17152,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
                        EX(called_scope) = ce;
                }
        }
-       if(IS_VAR != IS_UNUSED) {
+
+       if (IS_VAR == IS_CONST &&
+           IS_VAR == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_VAR != IS_CONST &&
+                  IS_VAR == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_VAR != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
                zend_free_op free_op2;
@@ -16729,8 +17189,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_VAR == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_VAR == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_VAR != IS_CONST) {
                        if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
                }
@@ -16938,7 +17404,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -17131,7 +17602,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD
                        zend_class_entry *ce;
 
                        if (IS_VAR == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -17601,7 +18077,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type,
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -17906,9 +18387,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
 
        if (IS_VAR == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -17920,7 +18406,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
                        EX(called_scope) = ce;
                }
        }
-       if(IS_UNUSED != IS_UNUSED) {
+
+       if (IS_VAR == IS_CONST &&
+           IS_UNUSED == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_VAR != IS_CONST &&
+                  IS_UNUSED == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_UNUSED != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
 
@@ -17948,8 +18443,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_UNUSED == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_VAR == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_UNUSED != IS_CONST) {
 
                }
@@ -18123,7 +18624,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -18180,7 +18686,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP
                        zend_class_entry *ce;
 
                        if (IS_UNUSED == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -19640,17 +20151,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CV != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CV == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -19686,9 +20207,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
 
        if (IS_VAR == IS_CONST) {
                /* no function found. try a static method in class */
-               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-               if (UNEXPECTED(ce == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+               if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                       ce = CACHED_PTR(opline->op1.literal->cache_slot);
+               } else {
+                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                       if (UNEXPECTED(ce == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(opline->op1.zv));
+                       }
+                       CACHE_PTR(opline->op1.literal->cache_slot, ce);
                }
                EX(called_scope) = ce;
        } else {
@@ -19700,7 +20226,16 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
                        EX(called_scope) = ce;
                }
        }
-       if(IS_CV != IS_UNUSED) {
+
+       if (IS_VAR == IS_CONST &&
+           IS_CV == IS_CONST &&
+           CACHED_PTR(opline->op2.literal->cache_slot)) {
+               EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot);
+       } else if (IS_VAR != IS_CONST &&
+                  IS_CV == IS_CONST &&
+                  (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) {
+               /* do nothing */
+       } else if (IS_CV != IS_UNUSED) {
                char *function_name_strval = NULL;
                int function_name_strlen = 0;
 
@@ -19728,8 +20263,14 @@ static int ZEND_FASTCALL  ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
                        if (UNEXPECTED(EX(fbc) == NULL)) {
                                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval);
                        }
+                       if (IS_CV == IS_CONST && EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0)) {
+                               if (IS_VAR == IS_CONST) {
+                                       CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc));
+                               } else {
+                                       CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc));
+                               }
+                       }
                }
-
                if (IS_CV != IS_CONST) {
 
                }
@@ -21098,17 +21639,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CONST != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CONST == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -21141,7 +21692,9 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
                zend_constant *c;
                zval *retval;
 
-               if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
+               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                       c = CACHED_PTR(opline->op2.literal->cache_slot);
+               } else if ((c = zend_quick_get_constant(opline->op2.literal + 1, opline->extended_value TSRMLS_CC)) == NULL) {
                        if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
                                char *actual = (char *)zend_memrchr(Z_STRVAL_P(opline->op2.zv), '\\', Z_STRLEN_P(opline->op2.zv));
                                if(!actual) {
@@ -21157,6 +21710,8 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
                        } else {
                                zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(opline->op2.zv));
                        }
+               } else {
+                       CACHE_PTR(opline->op2.literal->cache_slot, c);
                }
                retval = &EX_T(opline->result.var).tmp_var;
                INIT_PZVAL_COPY(retval, &c->value);
@@ -21169,13 +21724,29 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
                zval **value;
 
                if (IS_UNUSED == IS_CONST) {
-
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
-                       if (UNEXPECTED(ce == NULL)) {
-                               zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               value = CACHED_PTR(opline->op2.literal->cache_slot);
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       } else if (CACHED_PTR(opline->op1.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op1.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), opline->op1.literal + 1, opline->extended_value TSRMLS_CC);
+                               if (UNEXPECTED(ce == NULL)) {
+                                       zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(opline->op2.zv));
+                               }
+                               CACHE_PTR(opline->op1.literal->cache_slot, ce);
                        }
                } else {
                        ce = EX_T(opline->op1.var).class_entry;
+                       if ((value = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce)) != NULL) {
+                               ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
+                               zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
+                               CHECK_EXCEPTION();
+                               ZEND_VM_NEXT_OPCODE();
+                       }
                }
 
                if (EXPECTED(zend_hash_quick_find(&ce->constants_table, Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv)+1, Z_HASH_P(opline->op2.zv), (void **) &value) == SUCCESS)) {
@@ -21187,6 +21758,11 @@ static int ZEND_FASTCALL  ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
                                zval_update_constant(value, (void *) 1 TSRMLS_CC);
                                EG(scope) = old_scope;
                        }
+                       if (IS_UNUSED == IS_CONST) {
+                               CACHE_PTR(opline->op2.literal->cache_slot, value);
+                       } else {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, value);
+                       }
                        ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, *value);
                        zval_copy_ctor(&EX_T(opline->result.var).tmp_var);
                } else {
@@ -22321,17 +22897,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_TMP_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_TMP_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -23479,17 +24065,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -24904,17 +25500,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CV != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CV == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -27191,7 +27797,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -27937,17 +28548,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CONST != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CONST == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -28139,7 +28760,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL
                zend_class_entry *ce;
 
                if (IS_CONST == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -28330,7 +28956,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO
                        zend_class_entry *ce;
 
                        if (IS_CONST == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -29880,17 +30511,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_TMP_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_TMP_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -31096,7 +31737,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -31897,17 +32543,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_VAR != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_VAR == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
@@ -32101,7 +32757,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER
                zend_class_entry *ce;
 
                if (IS_VAR == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -32292,7 +32953,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE
                        zend_class_entry *ce;
 
                        if (IS_VAR == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -32759,7 +33425,12 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type,
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -33187,7 +33858,12 @@ static int ZEND_FASTCALL  ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND
                zend_class_entry *ce;
 
                if (IS_UNUSED == IS_CONST) {
-                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                       if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                               ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                       } else {
+                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                       }
                } else {
                        ce = EX_T(opline->op2.var).class_entry;
                }
@@ -33244,7 +33920,12 @@ static int ZEND_FASTCALL  ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC
                        zend_class_entry *ce;
 
                        if (IS_UNUSED == IS_CONST) {
-                               ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                               if (CACHED_PTR(opline->op2.literal->cache_slot)) {
+                                       ce = CACHED_PTR(opline->op2.literal->cache_slot);
+                               } else {
+                                       ce = zend_fetch_class_by_name(Z_STRVAL_P(opline->op2.zv), Z_STRLEN_P(opline->op2.zv), opline->op2.literal + 1, 0 TSRMLS_CC);
+                                       CACHE_PTR(opline->op2.literal->cache_slot, ce);
+                               }
                        } else {
                                ce = EX_T(opline->op2.var).class_entry;
                        }
@@ -34695,17 +35376,27 @@ static int ZEND_FASTCALL  ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H
 
        if (EXPECTED(EX(object) != NULL) &&
            EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) {
-               if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Object does not support method calls");
-               }
+               EX(called_scope) = Z_OBJCE_P(EX(object));
 
-               /* First, locate the function. */
-               EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
-               if (UNEXPECTED(EX(fbc) == NULL)) {
-                       zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
-               }
+               if (IS_CV != IS_CONST ||
+                   (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) {
+                   zval *object = EX(object);
 
-               EX(called_scope) = Z_OBJCE_P(EX(object));
+                       if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Object does not support method calls");
+                       }
+
+                       /* First, locate the function. */
+                       EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC);
+                       if (UNEXPECTED(EX(fbc) == NULL)) {
+                               zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+                       }
+                       if (IS_CV == IS_CONST &&
+                           EXPECTED((EX(fbc)->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) &&
+                           EXPECTED(EX(object) == object)) {
+                               CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc));
+                       }
+               }
        } else {
                zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
        }
index 6f6fed98340cc23f7482f759e7d3f25dc69956ae..05584d6fb3af5fa3033a4c870a581ab2f305d9c2 100644 (file)
@@ -39,6 +39,10 @@ zend_vm_enter:
 
        LOAD_REGS();
 
+       if (!op_array->run_time_cache && op_array->last_cache_slot) {
+               op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
+       }
+
        if (op_array->this_var != -1 && EG(This)) {
                Z_ADDREF_P(EG(This)); /* For $this pointer */
                if (!EG(active_symbol_table)) {
index a9df4e476c49543fa8141c5c3a550333a9e03864..c974846a73f9b9eabc95558bd212f52b42e87f82 100644 (file)
@@ -2011,7 +2011,6 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
 {
        php_date_obj *intern;
        zend_object_value retval;
-       zval *tmp;
 
        intern = emalloc(sizeof(php_date_obj));
        memset(intern, 0, sizeof(php_date_obj));
@@ -2020,7 +2019,7 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_
        }
        
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
        
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC);
        retval.handlers = &date_object_handlers_date;
@@ -2084,7 +2083,7 @@ static HashTable *date_object_get_properties(zval *object TSRMLS_DC)
 
        dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC);
 
-       props = dateobj->std.properties;
+       props = zend_std_get_properties(object TSRMLS_CC);
 
        if (!dateobj->time || GC_G(gc_active)) {
                return props;
@@ -2132,7 +2131,6 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
 {
        php_timezone_obj *intern;
        zend_object_value retval;
-       zval *tmp;
 
        intern = emalloc(sizeof(php_timezone_obj));
        memset(intern, 0, sizeof(php_timezone_obj));
@@ -2141,7 +2139,7 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl
        }
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
        
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC);
        retval.handlers = &date_object_handlers_timezone;
@@ -2184,7 +2182,6 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
 {
        php_interval_obj *intern;
        zend_object_value retval;
-       zval *tmp;
 
        intern = emalloc(sizeof(php_interval_obj));
        memset(intern, 0, sizeof(php_interval_obj));
@@ -2193,7 +2190,7 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl
        }
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
        
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC);
        retval.handlers = &date_object_handlers_interval;
@@ -2227,7 +2224,7 @@ static HashTable *date_object_get_properties_interval(zval *object TSRMLS_DC)
 
        intervalobj = (php_interval_obj *) zend_object_store_get_object(object TSRMLS_CC);
 
-       props = intervalobj->std.properties;
+       props = zend_std_get_properties(object TSRMLS_CC);
 
        if (!intervalobj->initialized || GC_G(gc_active)) {
                return props;
@@ -2260,7 +2257,6 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
 {
        php_period_obj *intern;
        zend_object_value retval;
-       zval *tmp;
 
        intern = emalloc(sizeof(php_period_obj));
        memset(intern, 0, sizeof(php_period_obj));
@@ -2269,7 +2265,7 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas
        }
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
        
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC);
        retval.handlers = &date_object_handlers_period;
index eb364a73b284ef194155278be06e2b93ea4f0966..9a6367c23dea85b16e4ca12532e57e8526baa060 100644 (file)
@@ -1053,7 +1053,6 @@ void dom_namednode_iter(dom_object *basenode, int ntype, dom_object *intern, xml
 static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool hash_copy TSRMLS_DC) /* {{{ */
 {
        zend_class_entry *base_class;
-       zval *tmp;
        dom_object *intern;
 
        if (instanceof_function(class_type, dom_xpath_class_entry TSRMLS_CC)) {
@@ -1075,7 +1074,7 @@ static dom_object* dom_objects_set_class(zend_class_entry *class_type, zend_bool
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
        if (hash_copy) {
-               zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+               object_properties_init(&intern->std, class_type);
        }
 
        return intern;
index 81ee428e943234ef86f418b7475d500073b302b3..f9b4c300510ce50ddf20e0490cf657872ac95101 100644 (file)
@@ -98,13 +98,12 @@ PHP_FILEINFO_API zend_object_value finfo_objects_new(zend_class_entry *class_typ
 {
        zend_object_value retval;
        struct finfo_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(struct finfo_object));
        memset(intern, 0, sizeof(struct finfo_object));
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        intern->ptr = NULL;
 
index a82a3f1716f2eee528c37b9c174c188aee1989ff..66b1f6f7d94e3c9d11f3f115ff62b502f32a19ba 100644 (file)
@@ -484,7 +484,6 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
 {
        zend_object_value retval;
        mysqli_object *intern;
-       zval *tmp;
        zend_class_entry *mysqli_base_class;
        zend_objects_free_object_storage_t free_storage;
 
@@ -502,8 +501,7 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry *class_
                                        (void **) &intern->prop_handler);
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
-                                       (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        /* link object */
        if (instanceof_function(class_type, mysqli_link_class_entry TSRMLS_CC)) {
index 404619e9c155e8cc508abd838f67878de688092a..157329042041577bea5a5c59521b8111e5830192 100755 (executable)
@@ -1552,12 +1552,12 @@ zend_object_value pdo_dbh_new(zend_class_entry *ce TSRMLS_DC)
 {
        zend_object_value retval;
        pdo_dbh_t *dbh;
-       zval *tmp;
 
        dbh = emalloc(sizeof(*dbh));
        memset(dbh, 0, sizeof(*dbh));
        zend_object_std_init(&dbh->std, ce TSRMLS_CC);
-       zend_hash_copy(dbh->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&dbh->std, ce);
+       rebuild_object_properties(&dbh->std);
        dbh->refcount = 1;
        dbh->def_stmt_ce = pdo_dbstmt_ce;
        
index 40d10c54b3fb8b33ddaf40f1d6815b9d44e4eaef..5e761053f13598bb9a57321addfcf81a7b81647d 100755 (executable)
@@ -2313,14 +2313,13 @@ static int dbstmt_compare(zval *object1, zval *object2 TSRMLS_DC)
 static zend_object_value dbstmt_clone_obj(zval *zobject TSRMLS_DC)
 {
        zend_object_value retval;
-       zval *tmp;
        pdo_stmt_t *stmt;
        pdo_stmt_t *old_stmt;
        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
 
        stmt = ecalloc(1, sizeof(*stmt));
        zend_object_std_init(&stmt->std, Z_OBJCE_P(zobject) TSRMLS_CC);
-       zend_hash_copy(stmt->std.properties, &stmt->std.ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&stmt->std, Z_OBJCE_P(zobject));
        stmt->refcount = 1;
 
        old_stmt = (pdo_stmt_t *)zend_object_store_get_object(zobject TSRMLS_CC);
@@ -2436,13 +2435,12 @@ void pdo_dbstmt_free_storage(pdo_stmt_t *stmt TSRMLS_DC)
 zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
 {
        zend_object_value retval;
-       zval *tmp;
 
        pdo_stmt_t *stmt;
        stmt = emalloc(sizeof(*stmt));
        memset(stmt, 0, sizeof(*stmt));
        zend_object_std_init(&stmt->std, ce TSRMLS_CC);
-       zend_hash_copy(stmt->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&stmt->std, ce);
        stmt->refcount = 1;
 
        retval.handle = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_dbstmt_free_storage, (zend_objects_store_clone_t)dbstmt_clone_obj TSRMLS_CC);
@@ -2680,6 +2678,9 @@ static HashTable *row_get_properties(zval *object TSRMLS_DC)
                return NULL;
        }
        
+       if (!stmt->std.properties) {
+               rebuild_object_properties(&stmt->std);
+       }
        for (i = 0; i < stmt->column_count; i++) {
                zval *val;
                MAKE_STD_ZVAL(val);
index 315580615d042a8022218cc107de53e3da6d72be..c1919afb5ffa0346f613d989dbd08de867e55377 100644 (file)
 #include "zend_closures.h"
 #include "zend_extensions.h"
 
+#define reflection_update_property(object, name, value) do { \
+               zval *member; \
+               MAKE_STD_ZVAL(member); \
+               ZVAL_STRINGL(member, name, sizeof(name)-1, 1); \
+               zend_std_write_property(object, member, value, NULL TSRMLS_CC); \
+               Z_DELREF_P(value); \
+               zval_ptr_dtor(&member); \
+       } while (0)
+
 /* Class entry pointers */
 PHPAPI zend_class_entry *reflector_ptr;
 PHPAPI zend_class_entry *reflection_exception_ptr;
@@ -296,7 +305,6 @@ static void reflection_free_objects_storage(void *object TSRMLS_DC)
 
 static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)
 {
-       zval tmp;
        zend_object_value retval;
        reflection_object *intern;
 
@@ -304,7 +312,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
        intern->zo.ce = class_type;
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
        retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
        retval.handlers = &reflection_object_handlers;
        return retval;
@@ -1157,7 +1165,7 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSR
        intern->ptr = ce;
        intern->ref_type = REF_TYPE_OTHER;
        intern->ce = ce;
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
 }
 /* }}} */
 
@@ -1186,7 +1194,7 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
        intern->ptr = module;
        intern->ref_type = REF_TYPE_OTHER;
        intern->ce = NULL;
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
 }
 /* }}} */
 
@@ -1217,7 +1225,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
        intern->ref_type = REF_TYPE_PARAMETER;
        intern->ce = fptr->common.scope;
        intern->obj = closure_object;
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
 }
 /* }}} */
 
@@ -1239,7 +1247,7 @@ static void reflection_function_factory(zend_function *function, zval *closure_o
        intern->ref_type = REF_TYPE_FUNCTION;
        intern->ce = NULL;
        intern->obj = closure_object;
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
 }
 /* }}} */
 
@@ -1263,8 +1271,8 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
        intern->ref_type = REF_TYPE_FUNCTION;
        intern->ce = ce;
        intern->obj = closure_object;
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
-       zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
+       reflection_update_property(object, "class", classname);
 }
 /* }}} */
 
@@ -1310,8 +1318,8 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
        intern->ref_type = REF_TYPE_PROPERTY;
        intern->ce = ce;
        intern->ignore_visibility = 0;
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
-       zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
+       reflection_update_property(object, "class", classname);
 }
 /* }}} */
 
@@ -1556,7 +1564,7 @@ ZEND_METHOD(reflection_function, __construct)
 
        MAKE_STD_ZVAL(name);
        ZVAL_STRING(name, fptr->common.function_name, 1);
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name TSRMLS_CC);
        intern->ptr = fptr;
        intern->ref_type = REF_TYPE_FUNCTION;
        intern->obj = closure;
@@ -2185,7 +2193,7 @@ ZEND_METHOD(reflection_parameter, __construct)
        } else {
                ZVAL_NULL(name);
        }
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
 
        ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
        ref->arg_info = &arg_info[position];
@@ -2663,11 +2671,11 @@ ZEND_METHOD(reflection_method, __construct)
        MAKE_STD_ZVAL(classname);
        ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1);
 
-       zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
+       reflection_update_property(object, "class", classname);
        
        MAKE_STD_ZVAL(name);
        ZVAL_STRING(name, mptr->common.function_name, 1);
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
        intern->ptr = mptr;
        intern->ref_type = REF_TYPE_FUNCTION;
        intern->ce = ce;
@@ -3202,7 +3210,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
        if (Z_TYPE_P(argument) == IS_OBJECT) {
                MAKE_STD_ZVAL(classname);
                ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
-               zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
+               reflection_update_property(object, "name", classname);
                intern->ptr = Z_OBJCE_P(argument);
                if (is_object) {
                        intern->obj = argument;
@@ -3219,7 +3227,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
 
                MAKE_STD_ZVAL(classname);
                ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
-               zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
+               reflection_update_property(object, "name", classname);
 
                intern->ptr = *ce;
        }
@@ -3235,14 +3243,63 @@ ZEND_METHOD(reflection_class, __construct)
 }
 /* }}} */
 
+/* {{{ add_class_vars */
+static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value TSRMLS_DC)
+{
+       HashPosition pos;
+       zend_property_info *prop_info;
+       zval *prop, *prop_copy;
+       char *key;
+       uint key_len;
+       ulong num_index;
+
+       zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
+       while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS) {
+               zend_hash_get_current_key_ex(&ce->properties_info, &key, &key_len, &num_index, 0, &pos);
+               zend_hash_move_forward_ex(&ce->properties_info, &pos);
+               if (((prop_info->flags & ZEND_ACC_SHADOW) &&
+                    prop_info->ce != ce) ||
+                   ((prop_info->flags & ZEND_ACC_PROTECTED) &&
+                    !zend_check_protected(prop_info->ce, ce)) ||
+                   ((prop_info->flags & ZEND_ACC_PRIVATE) &&
+                    prop_info->ce != ce)) {
+                       continue;
+               }
+               prop = NULL;
+               if (prop_info->offset >= 0) {
+                       if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
+                               prop = ce->default_static_members_table[prop_info->offset];
+                       } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
+                               prop = ce->default_properties_table[prop_info->offset];
+                       }
+               }
+               if (!prop) {
+                       continue;
+               }
+
+               /* copy: enforce read only access */
+               ALLOC_ZVAL(prop_copy);
+               *prop_copy = *prop;
+               zval_copy_ctor(prop_copy);
+               INIT_PZVAL(prop_copy);
+
+               /* this is necessary to make it able to work with default array 
+               * properties, returned to user */
+               if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || (Z_TYPE_P(prop_copy) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
+                       zval_update_constant(&prop_copy, 1 TSRMLS_CC);
+               }
+
+               add_assoc_zval(return_value, key, prop_copy);
+       }
+}
+/* }}} */
+
 /* {{{ proto public array ReflectionClass::getStaticProperties()
    Returns an associative array containing all static property values of the class */
 ZEND_METHOD(reflection_class, getStaticProperties)
 {
        reflection_object *intern;
        zend_class_entry *ce;
-       HashPosition pos;
-       zval **value;
 
        if (zend_parse_parameters_none() == FAILURE) {
                return;
@@ -3253,31 +3310,7 @@ ZEND_METHOD(reflection_class, getStaticProperties)
        zend_update_class_constants(ce TSRMLS_CC);
 
        array_init(return_value);
-
-       zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
-
-       while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
-               uint key_len;
-               char *key;
-               ulong num_index;
-
-               if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) {
-                       char *prop_name, *class_name;
-                       zval *prop_copy;
-
-                       zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
-
-                       /* filter privates from base classes */
-                       if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) {
-                               /* copy: enforce read only access */
-                               ALLOC_ZVAL(prop_copy);
-                               MAKE_COPY_ZVAL(value, prop_copy);
-
-                               add_assoc_zval(return_value, prop_name, prop_copy);
-                       }
-               }
-               zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
-       }
+       add_class_vars(ce, 1, return_value TSRMLS_CC);
 }
 /* }}} */
 
@@ -3355,51 +3388,15 @@ ZEND_METHOD(reflection_class, getDefaultProperties)
 {
        reflection_object *intern;
        zend_class_entry *ce;
-       int count, i;
-       HashTable *ht_list[3];
        
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
        GET_REFLECTION_OBJECT_PTR(ce);
        array_init(return_value);
-
        zend_update_class_constants(ce TSRMLS_CC);
-
-       ht_list[0] = CE_STATIC_MEMBERS(ce);
-       ht_list[1] = &ce->default_properties;
-       ht_list[2] = NULL;
-
-       for (i = 0; ht_list[i] != NULL; i++) {
-
-               count = zend_hash_num_elements(ht_list[i]);
-               if (count > 0) {
-                       HashPosition pos;
-                       zval **prop;
-
-                       zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
-                       while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
-                               char *key, *class_name, *prop_name;
-                               uint key_len;
-                               ulong num_index;
-                               zval *prop_copy;
-
-                               zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
-                               zend_hash_move_forward_ex(ht_list[i], &pos);
-                               zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
-                               if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
-                                       /* filter privates from base classes */
-                                       continue;
-                               }
-
-                               /* copy: enforce read only access */
-                               ALLOC_ZVAL(prop_copy);
-                               MAKE_COPY_ZVAL(prop, prop_copy);
-
-                               add_assoc_zval(return_value, prop_name, prop_copy);
-                       }
-               }
-       }
+       add_class_vars(ce, 1, return_value TSRMLS_CC);
+       add_class_vars(ce, 0, return_value TSRMLS_CC);
 }
 /* }}} */
 
@@ -4564,8 +4561,8 @@ ZEND_METHOD(reflection_property, __construct)
                ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);  
                ZVAL_STRINGL(propname, name_str, name_len, 1);
        }
-       zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
+       reflection_update_property(object, "class", classname);
+       reflection_update_property(object, "name", propname);
 
        reference = (property_reference*) emalloc(sizeof(property_reference));
        if (dynam_prop) {
@@ -4690,7 +4687,7 @@ ZEND_METHOD(reflection_property, getValue)
        reflection_object *intern;
        property_reference *ref;
        zval *object, name;
-       zval **member = NULL, *member_p = NULL;
+       zval *member_p = NULL;
 
        METHOD_NOTSTATIC(reflection_property_ptr);
        GET_REFLECTION_OBJECT_PTR(ref);
@@ -4705,11 +4702,13 @@ ZEND_METHOD(reflection_property, getValue)
 
        if ((ref->prop.flags & ZEND_ACC_STATIC)) {
                zend_update_class_constants(intern->ce TSRMLS_CC);
-               if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) {
+               if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
                        /* Bails out */
                }
-               MAKE_COPY_ZVAL(member, return_value);
+               *return_value= *CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+               zval_copy_ctor(return_value);
+               INIT_PZVAL(return_value);
        } else {
                char *class_name, *prop_name;
                
@@ -4738,7 +4737,6 @@ ZEND_METHOD(reflection_property, setValue)
        zval *value;
        int setter_done = 0;
        zval *tmp;
-       HashTable *prop_table;
 
        METHOD_NOTSTATIC(reflection_property_ptr);
        GET_REFLECTION_OBJECT_PTR(ref);
@@ -4758,33 +4756,34 @@ ZEND_METHOD(reflection_property, setValue)
                        }
                }
                zend_update_class_constants(intern->ce TSRMLS_CC);
-               prop_table = CE_STATIC_MEMBERS(intern->ce);
 
-               if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) {
+               if (!CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) {
                        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
                        /* Bails out */
                }
-               if (*variable_ptr == value) {
-                       setter_done = 1;
-               } else {
+               variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
+               if (*variable_ptr != value) {
                        if (PZVAL_IS_REF(*variable_ptr)) {
-                               zval_dtor(*variable_ptr);
-                               (*variable_ptr)->type = value->type;
+                               zval garbage = **variable_ptr; /* old value should be destroyed */
+
+                               /* To check: can't *variable_ptr be some system variable like error_zval here? */
+                               Z_TYPE_PP(variable_ptr) = Z_TYPE_P(value);
                                (*variable_ptr)->value = value->value;
                                if (Z_REFCOUNT_P(value) > 0) {
                                        zval_copy_ctor(*variable_ptr);
                                }
-                               setter_done = 1;
-                       }
-               }
-               if (!setter_done) {
-                       zval **foo;
+                               zval_dtor(&garbage);
+                       } else {
+                               zval *garbage = *variable_ptr;
 
-                       Z_ADDREF_P(value);
-                       if (PZVAL_IS_REF(value)) {
-                               SEPARATE_ZVAL(&value);
+                               /* if we assign referenced variable, we should separate it */
+                               Z_ADDREF_P(value);
+                               if (PZVAL_IS_REF(value)) {
+                                       SEPARATE_ZVAL(&value);
+                               }
+                               *variable_ptr = value;
+                               zval_ptr_dtor(&garbage);
                        }
-                       zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
                }
        } else {
                char *class_name, *prop_name;
@@ -4917,7 +4916,7 @@ ZEND_METHOD(reflection_extension, __construct)
        free_alloca(lcname, use_heap);
        MAKE_STD_ZVAL(name);
        ZVAL_STRING(name, module->name, 1);
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property( object, "name", name);
        intern->ptr = module;
        intern->ref_type = REF_TYPE_OTHER;
        intern->ce = NULL;
@@ -5269,7 +5268,7 @@ ZEND_METHOD(reflection_zend_extension, __construct)
        }
        MAKE_STD_ZVAL(name);
        ZVAL_STRING(name, extension->name, 1);
-       zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
+       reflection_update_property(object, "name", name);
        intern->ptr = extension;
        intern->ref_type = REF_TYPE_OTHER;
        intern->ce = NULL;
@@ -5783,7 +5782,7 @@ static zend_object_handlers *zend_std_obj_handlers;
 static void _reflection_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
 {
        if ((Z_TYPE_P(member) == IS_STRING)
-               && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
+               && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
                && ((Z_STRLEN_P(member) == sizeof("name") - 1  && !memcmp(Z_STRVAL_P(member), "name",  sizeof("name")))
                        || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
        {
index 733c4c7e4dd3f638743993034bd257310963dff8..ffd81ffb874666b1253250cf3822bf8c0eb9ceb7 100644 (file)
@@ -3,6 +3,8 @@ ReflectionClass::getStaticPropertyValue()
 --CREDITS--
 Robin Fernandes <robinf@php.net>
 Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
 --FILE--
 <?php
 class A {
diff --git a/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt b/ext/reflection/tests/ReflectionClass_getStaticPropertyValue_001_2_4.phpt
new file mode 100644 (file)
index 0000000..c299412
--- /dev/null
@@ -0,0 +1,61 @@
+--TEST--
+ReflectionClass::getStaticPropertyValue() 
+--CREDITS--
+Robin Fernandes <robinf@php.net>
+Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+class A {
+       static private $privateOverridden = "original private";
+       static protected $protectedOverridden = "original protected";
+       static public $publicOverridden = "original public";
+}
+
+class B extends A {
+       static private $privateOverridden = "changed private";
+       static protected $protectedOverridden = "changed protected";
+       static public $publicOverridden = "changed public";
+}
+
+echo "Retrieving static values from A:\n";
+$rcA = new ReflectionClass('A');
+var_dump($rcA->getStaticPropertyValue("privateOverridden", "default value"));
+var_dump($rcA->getStaticPropertyValue("\0A\0privateOverridden"));
+var_dump($rcA->getStaticPropertyValue("protectedOverridden", "default value"));
+var_dump($rcA->getStaticPropertyValue("\0*\0protectedOverridden"));
+var_dump($rcA->getStaticPropertyValue("publicOverridden"));
+
+echo "\nRetrieving static values from B:\n";
+$rcB = new ReflectionClass('B');
+var_dump($rcB->getStaticPropertyValue("\0A\0privateOverridden"));
+var_dump($rcB->getStaticPropertyValue("\0B\0privateOverridden"));
+var_dump($rcB->getStaticPropertyValue("\0*\0protectedOverridden"));
+var_dump($rcB->getStaticPropertyValue("publicOverridden"));
+
+echo "\nRetrieving non-existent values from A with no default value:\n";
+try {
+       var_dump($rcA->getStaticPropertyValue("protectedOverridden"));
+       echo "you should not see this";
+} catch (Exception $e) {
+       echo $e->getMessage() . "\n";
+}
+
+try {
+       var_dump($rcA->getStaticPropertyValue("privateOverridden"));
+       echo "you should not see this"; 
+} catch (Exception $e) {
+       echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECTF--
+Retrieving static values from A:
+string(13) "default value"
+
+Fatal error: Uncaught exception 'ReflectionException' with message 'Class A does not have a property named ' in %sReflectionClass_getStaticPropertyValue_001_2_4.php:%d
+Stack trace:
+#0 %sReflectionClass_getStaticPropertyValue_001_2_4.php(%d): ReflectionClass->getStaticPropertyValue('?A?privateOverr...')
+#1 {main}
+  thrown in %sReflectionClass_getStaticPropertyValue_001_2_4.php on line %d
index 082ef676cd0ba0d0a8a0f008a97ce2cdde643eb8..9e8f01e6796ce8499d4337b766cc56ba140b19eb 100644 (file)
@@ -3,6 +3,8 @@ ReflectionClass::setStaticPropertyValue()
 --CREDITS--
 Robin Fernandes <robinf@php.net>
 Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
 --FILE--
 <?php
 class A {
diff --git a/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt b/ext/reflection/tests/ReflectionClass_setStaticPropertyValue_001_2_4.phpt
new file mode 100644 (file)
index 0000000..1092f65
--- /dev/null
@@ -0,0 +1,61 @@
+--TEST--
+ReflectionClass::setStaticPropertyValue() 
+--CREDITS--
+Robin Fernandes <robinf@php.net>
+Steve Seear <stevseea@php.net>
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+class A {
+       static private $privateOverridden = "original private";
+       static protected $protectedOverridden = "original protected";
+       static public $publicOverridden = "original public";
+}
+
+class B extends A {
+       static private $privateOverridden = "changed private";
+       static protected $protectedOverridden = "changed protected";
+       static public $publicOverridden = "changed public";
+}
+
+echo "Set static values in A:\n";
+$rcA = new ReflectionClass('A');
+$rcA->setStaticPropertyValue("\0A\0privateOverridden", "new value 1");
+$rcA->setStaticPropertyValue("\0*\0protectedOverridden", "new value 2");
+$rcA->setStaticPropertyValue("publicOverridden", "new value 3");
+print_r($rcA->getStaticProperties());
+
+echo "\nSet static values in B:\n";
+$rcB = new ReflectionClass('B');
+$rcB->setStaticPropertyValue("\0A\0privateOverridden", "new value 4");
+$rcB->setStaticPropertyValue("\0B\0privateOverridden", "new value 5");
+$rcB->setStaticPropertyValue("\0*\0protectedOverridden", "new value 6");
+$rcB->setStaticPropertyValue("publicOverridden", "new value 7");
+print_r($rcA->getStaticProperties());
+print_r($rcB->getStaticProperties());
+
+echo "\nSet non-existent values from A with no default value:\n";
+try {
+       var_dump($rcA->setStaticPropertyValue("protectedOverridden", "new value 8"));
+       echo "you should not see this";
+} catch (Exception $e) {
+       echo $e->getMessage() . "\n";
+}
+
+try {
+       var_dump($rcA->setStaticPropertyValue("privateOverridden", "new value 9"));
+       echo "you should not see this"; 
+} catch (Exception $e) {
+       echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECTF--
+Set static values in A:
+
+Fatal error: Uncaught exception 'ReflectionException' with message 'Class A does not have a property named ' in %sReflectionClass_setStaticPropertyValue_001_2_4.php:%d
+Stack trace:
+#0 %sReflectionClass_setStaticPropertyValue_001_2_4.php(%d): ReflectionClass->setStaticPropertyValue('?A?privateOverr...', 'new value 1')
+#1 {main}
+  thrown in %sReflectionClass_setStaticPropertyValue_001_2_4.php on line %d
index b061125f9726832ef00d75ef9b873f7b7f6158ce..f98e8fa16e7291a84b6b3674dcd640f27895442a 100755 (executable)
@@ -81,11 +81,17 @@ typedef struct _spl_array_object {
 
 static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */
        if ((intern->ar_flags & SPL_ARRAY_IS_SELF) != 0) {
+               if (!intern->std.properties) {
+                       rebuild_object_properties(&intern->std);
+               }
                return intern->std.properties;
        } else if ((intern->ar_flags & SPL_ARRAY_USE_OTHER) && (check_std_props == 0 || (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) == 0) && Z_TYPE_P(intern->array) == IS_OBJECT) {
                spl_array_object *other  = (spl_array_object*)zend_object_store_get_object(intern->array TSRMLS_CC);
                return spl_array_get_hash_table(other, check_std_props TSRMLS_CC);
        } else if ((intern->ar_flags & ((check_std_props ? SPL_ARRAY_STD_PROP_LIST : 0) | SPL_ARRAY_IS_SELF)) != 0) {
+               if (!intern->std.properties) {
+                       rebuild_object_properties(&intern->std);
+               }
                return intern->std.properties;
        } else {
                return HASH_OF(intern->array);
@@ -173,7 +179,7 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
        ALLOC_INIT_ZVAL(intern->retval);
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        intern->ar_flags = 0;
        intern->serialize_data   = NULL;
@@ -728,6 +734,10 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /*
 
        *is_temp = 0;
 
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
+       }
+
        if (HASH_OF(intern->array) == intern->std.properties) {
                return intern->std.properties;
        } else {
@@ -1584,6 +1594,9 @@ smart_str spl_array_serialize_helper(spl_array_object *intern, php_serialize_dat
        /* members */
        smart_str_appendl(&buf, "m:", 2);
        INIT_PZVAL(&members);
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
+       }
        Z_ARRVAL(members) = intern->std.properties;
        Z_TYPE(members) = IS_ARRAY;
        pmembers = &members;
@@ -1719,6 +1732,9 @@ void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char
        }
 
        /* copy members */
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
+       }
        zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
        zval_ptr_dtor(&pmembers);
 
index 23044122a97c38881933f30e60ed0466125738d6..cc049a1e27b021f4c18feeb4579d1fe90c26d657 100755 (executable)
@@ -136,7 +136,6 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
 {
        zend_object_value retval;
        spl_filesystem_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(spl_filesystem_object));
        memset(intern, 0, sizeof(spl_filesystem_object));
@@ -146,7 +145,7 @@ static zend_object_value spl_filesystem_object_new_ex(zend_class_entry *class_ty
        if (obj) *obj = intern;
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_filesystem_object_free_storage, NULL TSRMLS_CC);
        retval.handlers = &spl_filesystem_object_handlers;
@@ -549,6 +548,10 @@ static HashTable* spl_filesystem_object_get_debug_info(zval *obj, int *is_temp T
 
        *is_temp = 1;
 
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
+       }
+
        ALLOC_HASHTABLE(rv);
        ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 3, 0);
 
index af7389cf65241dacbafc3a5edbc5db7d1884f5cd..d3b0b38b91f4bd1cd8880e9e508b210e3609ff1e 100644 (file)
@@ -367,7 +367,6 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type,
 {
        zend_object_value  retval;
        spl_dllist_object *intern;
-       zval              *tmp;
        zend_class_entry  *parent = class_type;
        int                inherited = 0;
 
@@ -376,7 +375,7 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type,
        ALLOC_INIT_ZVAL(intern->retval);
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        intern->flags = 0;
        intern->traverse_position = 0;
@@ -523,6 +522,9 @@ static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRML
                INIT_PZVAL(&zrv);
                Z_ARRVAL(zrv) = intern->debug_info;
 
+               if (!intern->std.properties) {
+                       rebuild_object_properties(&intern->std);
+               }
                zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 
                pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
index 783c854e5ef6872fed6f02c7268b751e2cb254bf..73f5fcbd01d7469d2520d347986f6068d512de3d 100644 (file)
@@ -150,21 +150,22 @@ static void spl_fixedarray_copy(spl_fixedarray *to, spl_fixedarray *from TSRMLS_
 static HashTable* spl_fixedarray_object_get_properties(zval *obj TSRMLS_DC) /* {{{{ */
 {
        spl_fixedarray_object *intern  = (spl_fixedarray_object*)zend_object_store_get_object(obj TSRMLS_CC);
+       HashTable *ht = zend_std_get_properties(obj TSRMLS_CC);
        int  i = 0;
 
        if (intern->array) {
                for (i = 0; i < intern->array->size; i++) {
                        if (intern->array->elements[i]) {
-                               zend_hash_index_update(intern->std.properties, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
+                               zend_hash_index_update(ht, i, (void *)&intern->array->elements[i], sizeof(zval *), NULL);
                                Z_ADDREF_P(intern->array->elements[i]);
                        } else {
-                               zend_hash_index_update(intern->std.properties, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
+                               zend_hash_index_update(ht, i, (void *)&EG(uninitialized_zval_ptr), sizeof(zval *), NULL);
                                Z_ADDREF_P(EG(uninitialized_zval_ptr));
                        }
                }
        }
 
-       return intern->std.properties;
+       return ht;
 }
 /* }}}} */
 
@@ -199,7 +200,6 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty
 {
        zend_object_value     retval;
        spl_fixedarray_object *intern;
-       zval                 *tmp;
        zend_class_entry     *parent = class_type;
        int                   inherited = 0;
 
@@ -208,7 +208,7 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty
        ALLOC_INIT_ZVAL(intern->retval);
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        intern->current = 0;
        intern->flags = 0;
index 6f11ef92cf94a2aa1c9ce5169698efaf9a0e9b8e..45ec68096a32452f9bfdd3b78ba07ad94375f80c 100644 (file)
@@ -385,7 +385,6 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp
 {
        zend_object_value  retval;
        spl_heap_object   *intern;
-       zval              *tmp;
        zend_class_entry  *parent = class_type;
        int                inherited = 0;
 
@@ -394,7 +393,7 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp
        ALLOC_INIT_ZVAL(intern->retval);
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        intern->flags      = 0;
        intern->fptr_cmp   = NULL;
@@ -529,6 +528,10 @@ static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zv
 
        *is_temp = 0;
 
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
+       }
+
        if (intern->debug_info == NULL) {
                ALLOC_HASHTABLE(intern->debug_info);
                ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
index d71f4e80da0e21ebef3067b21dce847579956c07..c8d0e64461c05631cf381c19f19b3243faa36842 100755 (executable)
@@ -810,7 +810,6 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *
 {
        zend_object_value retval;
        spl_recursive_it_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(spl_recursive_it_object));
        memset(intern, 0, sizeof(spl_recursive_it_object));
@@ -825,7 +824,7 @@ static zend_object_value spl_RecursiveIteratorIterator_new_ex(zend_class_entry *
        }
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_RecursiveIteratorIterator_free_storage, NULL TSRMLS_CC);
        retval.handlers = &spl_handlers_rec_it_it;
@@ -1960,14 +1959,13 @@ static zend_object_value spl_dual_it_new(zend_class_entry *class_type TSRMLS_DC)
 {
        zend_object_value retval;
        spl_dual_it_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(spl_dual_it_object));
        memset(intern, 0, sizeof(spl_dual_it_object));
        intern->dit_type = DIT_Unknown;
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_dual_it_free_storage, NULL TSRMLS_CC);
        retval.handlers = &spl_handlers_dual_it;
index c8f80a1fdaa97002bc48c71682c63c95ad9c6a99..1e09ca98b9439af5cf8978c0c85d0edb5d95697b 100755 (executable)
@@ -253,14 +253,13 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type,
        zend_object_value     retval;
        spl_SplObjectStorage *intern;
        zend_class_entry     *parent = class_type;
-       zval                 *tmp;
 
        intern = emalloc(sizeof(spl_SplObjectStorage));
        memset(intern, 0, sizeof(spl_SplObjectStorage));
        *obj = intern;
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0);
 
@@ -669,7 +668,7 @@ SPL_METHOD(SplObjectStorage, serialize)
        /* members */
        smart_str_appendl(&buf, "m:", 2);
        INIT_PZVAL(&members);
-       Z_ARRVAL(members) = intern->std.properties;
+       Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC);
        Z_TYPE(members) = IS_ARRAY;
        pmembers = &members;
        php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
@@ -767,6 +766,9 @@ SPL_METHOD(SplObjectStorage, unserialize)
        }
 
        /* copy members */
+       if (!intern->std.properties) {
+               rebuild_object_properties(&intern->std);
+       }
        zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
        zval_ptr_dtor(&pmembers);
 
index db0dab40ba4144b18f9094dd6adaab055347f24d..1f33caf43b8d7649ed885c6788518b1e09365431 100644 (file)
@@ -1154,14 +1154,13 @@ static void sqlite_object_free_storage(void *object TSRMLS_DC)
 static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
 {
        sqlite_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(sqlite_object));
        memset(intern, 0, sizeof(sqlite_object));
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
+       object_properties_init(&intern->std, class_type);
+       
        retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) sqlite_object_free_storage, NULL TSRMLS_CC);
        retval->handlers = handlers;
 }
index 00364b0dd4942af7369691a6fec3798783137eb7..643e1a07bcb95066500cc1c5677b16a9638b0f3e 100644 (file)
@@ -1933,7 +1933,6 @@ static void php_sqlite3_result_object_free_storage(void *object TSRMLS_DC) /* {{
 
 static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
 {
-       zval *tmp;
        zend_object_value retval;
        php_sqlite3_db_object *intern;
 
@@ -1946,7 +1945,7 @@ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSR
        zend_llist_init(&(intern->free_list),   sizeof(php_sqlite3_free_list *), (llist_dtor_func_t)php_sqlite3_free_list_dtor, 0);
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_object_free_storage, NULL TSRMLS_CC);
        retval.handlers = (zend_object_handlers *) &sqlite3_object_handlers;
@@ -1957,7 +1956,6 @@ static zend_object_value php_sqlite3_object_new(zend_class_entry *class_type TSR
 
 static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
 {
-       zval *tmp;
        zend_object_value retval;
        php_sqlite3_stmt *intern;
 
@@ -1968,7 +1966,7 @@ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_typ
        intern->db_obj_zval = NULL;
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_stmt_object_free_storage, NULL TSRMLS_CC);
        retval.handlers = (zend_object_handlers *) &sqlite3_stmt_object_handlers;
@@ -1979,7 +1977,6 @@ static zend_object_value php_sqlite3_stmt_object_new(zend_class_entry *class_typ
 
 static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
 {
-       zval *tmp;
        zend_object_value retval;
        php_sqlite3_result *intern;
 
@@ -1992,7 +1989,7 @@ static zend_object_value php_sqlite3_result_object_new(zend_class_entry *class_t
        intern->stmt_obj_zval = NULL;
 
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) php_sqlite3_result_object_free_storage, NULL TSRMLS_CC);
        retval.handlers = (zend_object_handlers *) &sqlite3_result_object_handlers;
index ce9a95375a4240aed976e8aa8d233f11f17ed9bf..f42c64d8b9fbbf7317b221f3700d43bbbc72ecbe 100644 (file)
@@ -109,8 +109,6 @@ static zend_object_value php_create_incomplete_object(zend_class_entry *class_ty
        value = zend_objects_new(&object, class_type TSRMLS_CC);
        value.handlers = &php_incomplete_object_handlers;
        
-       ALLOC_HASHTABLE(object->properties);
-       zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
        return value;
 }
 
index 48aac60b5512de6099f019bb0513861e04e291c6..86773b17f8e052e928d838dc7c77b99f592dd1ae 100644 (file)
@@ -1,5 +1,7 @@
 --TEST--
 Test array_fill() function : usage variations - various object values for 'val' argument
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '>=')) die('skip ZendEngine 2.3 or below needed'); ?>
 --FILE--
 <?php
 /* Prototype  : array array_fill(int $start_key, int $num, mixed $val)
diff --git a/ext/standard/tests/array/array_fill_object_2_4.phpt b/ext/standard/tests/array/array_fill_object_2_4.phpt
new file mode 100644 (file)
index 0000000..fb81797
--- /dev/null
@@ -0,0 +1,434 @@
+--TEST--
+Test array_fill() function : usage variations - various object values for 'val' argument
+--SKIPIF--
+<?php if (version_compare(zend_version(), '2.4.0', '<')) die('skip ZendEngine 2.4 needed'); ?>
+--FILE--
+<?php
+/* Prototype  : array array_fill(int $start_key, int $num, mixed $val)
+ * Description: Create an array containing num elements starting with index start_key each initialized to val 
+ * Source code: ext/standard/array.c
+ */
+
+/*
+ * testing array_fill() by passing various  object values for 'val' argument
+ */
+
+echo "*** Testing array_fill() : usage variations ***\n";
+
+// Initialise function arguments not being substituted 
+$start_key = 0;
+$num = 2;
+
+// class without a member
+class Test
+{
+}
+
+//class with public member, static member , constant and consturctor to initialize the public member 
+class Test1
+{
+  const test1_constant = "test1";
+  public static $test1_static = 0;
+  public $member1;
+  var $var1 = 30;
+  var $var2;
+
+  function __construct($value1 , $value2)
+  {
+    $this->member1 = $value1;
+    $this->var2 = $value2;
+  }
+}
+
+// child class which inherits parent class test1
+class Child_test1 extends Test1
+{
+  public $member2;
+
+  function __construct($value1 , $value2 , $value3)
+  {
+    parent::__construct($value1 , $value2);
+    $this->member2 = $value3;
+  }
+}
+
+//class with private member, static member, constant and constructor to initialize the private member
+class Test2
+{
+  const test2_constant = "test2";
+  public static $test2_static = 0;
+  private $member1;
+  var $var1 = 30;
+  var $var2;
+
+  function __construct($value1 , $value2)
+  {
+    $this->member1 = $value1;
+    $this->var2 = $value2;
+  }
+}
+
+// child class which inherits parent class test2
+class Child_test2 extends Test2
+{
+  private $member1;
+
+  function __construct($value1 , $value2 , $value3)
+  {
+    parent::__construct($value1 , $value2);
+    $this->member1 = $value3;
+  }
+}
+
+// class with protected member, static member, constant and consturctor to initialize the protected member 
+class Test3
+{
+  const test3_constant = "test3";
+  public static $test3_static = 0;
+  protected $member1;
+  var $var1 = 30;
+  var $var2; 
+
+  function __construct($value1 , $value2)
+  {
+     $this->member1 = $value1;
+     $this->var2 = $value2;
+  }
+}
+
+// child class which inherits parent class test3
+class Child_test3 extends Test3
+{
+  protected $member1;
+
+  function __construct($value1 , $value2 , $value3)
+  {
+    parent::__construct($value1 , $value2);
+    $this->member1 = $value3;
+  }
+}
+
+// class with public, private, protected members, static, constant members and constructor to initialize all the members
+class Test4
+{
+  const test4_constant = "test4";
+  public static $test4_static = 0;
+  public $member1;
+  private $member2;
+  protected $member3;
+
+  function __construct($value1 , $value2 , $value3)
+  {
+    $this->member1 = $value1;
+    $this->member2 = $value2;
+    $this->member3 = $value3;
+  }
+}
+
+// child class which inherits parent class test4
+class Child_test4 extends Test4
+{
+  var $var1;
+  
+  function __construct($value1 , $value2 , $value3 , $value4)
+  {
+    parent::__construct($value1 , $value2 , $value3);
+    $this->var1 = $value4;
+  }
+}
+
+// abstract class with public, private, protected members 
+abstract class AbstractClass
+{
+  public $member1;
+  private $member2;
+  protected $member3;
+  var $var1 = 30;
+  
+  abstract protected function display();
+}
+
+// implement abstract 'AbstractClass' class
+class ConcreteClass1 extends AbstractClass
+{
+  protected function display()
+  {
+    echo "class name is ConcreteClass1 \n";
+  }
+}
+
+
+// declarationn of the interface 'iTemplate'
+interface iTemplate
+{
+  public function display();
+}
+
+// implement the interface 'iTemplate'
+class Template1 implements iTemplate
+{
+  public function display()
+  {
+    echo "class name is Template1\n";
+  }
+}
+
+//array of object values for 'val' argument
+$objects = array(
+  
+  /* 1  */  new Test(),
+            new Test1(100 , 101),
+            new Child_test1(100 , 101 , 102),
+            new Test2(100 , 101),
+  /* 5  */  new Child_test2(100 , 101 , 102),
+            new Test3(100 , 101),
+            new Child_test3(100 , 101 , 102),
+            new Test4( 100 , 101 , 102),
+            new Child_test4(100 , 101 , 102 , 103),
+            new ConcreteClass1(),
+  /* 11 */  new Template1()
+);
+
+// loop through each element of the array for 'val' argument 
+// check the working of array_fill()
+echo "--- Testing array_fill() with different object values for 'val' argument ---\n";
+$counter = 1;
+for($index = 0; $index < count($objects); $index ++)
+{
+  echo "-- Iteration $counter --\n";
+  $val = $objects[$index];
+
+  var_dump( array_fill($start_key,$num,$val) );
+
+  $counter++;
+}
+
+echo "Done";
+?>
+--EXPECTF--
+*** Testing array_fill() : usage variations ***
+--- Testing array_fill() with different object values for 'val' argument ---
+-- Iteration 1 --
+array(2) {
+  [0]=>
+  object(Test)#%d (0) {
+  }
+  [1]=>
+  object(Test)#%d (0) {
+  }
+}
+-- Iteration 2 --
+array(2) {
+  [0]=>
+  object(Test1)#%d (3) {
+    ["member1"]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+  [1]=>
+  object(Test1)#%d (3) {
+    ["member1"]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+}
+-- Iteration 3 --
+array(2) {
+  [0]=>
+  object(Child_test1)#%d (4) {
+    ["member2"]=>
+    int(102)
+    ["member1"]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+  [1]=>
+  object(Child_test1)#%d (4) {
+    ["member2"]=>
+    int(102)
+    ["member1"]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+}
+-- Iteration 4 --
+array(2) {
+  [0]=>
+  object(Test2)#%d (3) {
+    ["member1":"Test2":private]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+  [1]=>
+  object(Test2)#%d (3) {
+    ["member1":"Test2":private]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+}
+-- Iteration 5 --
+array(2) {
+  [0]=>
+  object(Child_test2)#%d (4) {
+    ["member1":"Child_test2":private]=>
+    int(102)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+    ["member1":"Test2":private]=>
+    int(100)
+  }
+  [1]=>
+  object(Child_test2)#%d (4) {
+    ["member1":"Child_test2":private]=>
+    int(102)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+    ["member1":"Test2":private]=>
+    int(100)
+  }
+}
+-- Iteration 6 --
+array(2) {
+  [0]=>
+  object(Test3)#%d (3) {
+    ["member1":protected]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+  [1]=>
+  object(Test3)#%d (3) {
+    ["member1":protected]=>
+    int(100)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+}
+-- Iteration 7 --
+array(2) {
+  [0]=>
+  object(Child_test3)#%d (3) {
+    ["member1":protected]=>
+    int(102)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+  [1]=>
+  object(Child_test3)#%d (3) {
+    ["member1":protected]=>
+    int(102)
+    ["var1"]=>
+    int(30)
+    ["var2"]=>
+    int(101)
+  }
+}
+-- Iteration 8 --
+array(2) {
+  [0]=>
+  object(Test4)#%d (3) {
+    ["member1"]=>
+    int(100)
+    ["member2":"Test4":private]=>
+    int(101)
+    ["member3":protected]=>
+    int(102)
+  }
+  [1]=>
+  object(Test4)#%d (3) {
+    ["member1"]=>
+    int(100)
+    ["member2":"Test4":private]=>
+    int(101)
+    ["member3":protected]=>
+    int(102)
+  }
+}
+-- Iteration 9 --
+array(2) {
+  [0]=>
+  object(Child_test4)#%d (4) {
+    ["var1"]=>
+    int(103)
+    ["member1"]=>
+    int(100)
+    ["member2":"Test4":private]=>
+    int(101)
+    ["member3":protected]=>
+    int(102)
+  }
+  [1]=>
+  object(Child_test4)#%d (4) {
+    ["var1"]=>
+    int(103)
+    ["member1"]=>
+    int(100)
+    ["member2":"Test4":private]=>
+    int(101)
+    ["member3":protected]=>
+    int(102)
+  }
+}
+-- Iteration 10 --
+array(2) {
+  [0]=>
+  object(ConcreteClass1)#%d (4) {
+    ["member1"]=>
+    NULL
+    ["member2":"AbstractClass":private]=>
+    NULL
+    ["member3":protected]=>
+    NULL
+    ["var1"]=>
+    int(30)
+  }
+  [1]=>
+  object(ConcreteClass1)#%d (4) {
+    ["member1"]=>
+    NULL
+    ["member2":"AbstractClass":private]=>
+    NULL
+    ["member3":protected]=>
+    NULL
+    ["var1"]=>
+    int(30)
+  }
+}
+-- Iteration 11 --
+array(2) {
+  [0]=>
+  object(Template1)#%d (0) {
+  }
+  [1]=>
+  object(Template1)#%d (0) {
+  }
+}
+Done
index 85d97408216a2e69551982c6c4e029d726ead27c..f48b4f5bf1eefee7d1521bb4dbe03a613b279bf2 100644 (file)
@@ -676,13 +676,11 @@ static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *
                                                        zend_object_value *retval, tidy_obj_type objtype TSRMLS_DC)
 {
        PHPTidyObj *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(PHPTidyObj));
        memset(intern, 0, sizeof(PHPTidyObj));
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
 
        switch(objtype) {
                case is_node:
index a151062184bafe07a3c5815974049da398b9403e..30de80f41d6eff274097fb2240f90ab6ac5c9d42 100644 (file)
@@ -391,7 +391,6 @@ zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
 {
        zend_object_value retval;
        xmlreader_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(xmlreader_object));
        memset(&intern->std, 0, sizeof(zend_object));
@@ -401,7 +400,7 @@ zend_object_value xmlreader_objects_new(zend_class_entry *class_type TSRMLS_DC)
        intern->prop_handler = &xmlreader_prop_handlers;
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) xmlreader_objects_free_storage, xmlreader_objects_clone TSRMLS_CC);
        intern->handle = retval.handle;
        retval.handlers = &xmlreader_object_handlers;
index e26c6dc7e1211a93f60cd42b9aa0624b465dacab..365fc82429b971da87d19a3a4cfc74a359297128 100644 (file)
@@ -143,7 +143,6 @@ static void xmlwriter_object_free_storage(void *object TSRMLS_DC)
 static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRMLS_DC)
 {
        ze_xmlwriter_object *intern;
-       zval *tmp;
        zend_object_value retval;
 
        intern = emalloc(sizeof(ze_xmlwriter_object));
@@ -151,8 +150,7 @@ static zend_object_value xmlwriter_object_new(zend_class_entry *class_type TSRML
        intern->xmlwriter_ptr = NULL;
        
        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
-                                       (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        retval.handle = zend_objects_store_put(intern,
                                                NULL,
index f177f42e6676f040570fd5dd1177b829e478cb3b..53e5e06b8d86b9a5c385287a44db427b4e57e48d 100644 (file)
@@ -115,7 +115,6 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
 {
        zend_object_value retval;
        xsl_object *intern;
-       zval *tmp;
 
        intern = emalloc(sizeof(xsl_object));
        intern->ptr = NULL;
@@ -129,7 +128,7 @@ zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC)
        intern->profiling = NULL;
 
        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->std, class_type);
        ALLOC_HASHTABLE(intern->parameter);
        zend_hash_init(intern->parameter, 0, NULL, ZVAL_PTR_DTOR, 0);
        ALLOC_HASHTABLE(intern->registered_phpfunctions);
index ba89cce5f3c5584e5be48f88830a5e4c5baac79d..7645c56ada6130609657a17ea9d434d2e578bdb0 100644 (file)
@@ -971,7 +971,7 @@ static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
        ulong num_key;
 
        obj = (ze_zip_object *)zend_objects_get_address(object TSRMLS_CC);
-       props = obj->zo.properties;
+       props = zend_std_get_properties(object TSRMLS_CC);
 
        if (obj->prop_handler == NULL) {
                return NULL;
@@ -988,7 +988,7 @@ static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
                zend_hash_update(props, key, key_len, (void *)&val, sizeof(zval *), NULL);
                zend_hash_move_forward_ex(obj->prop_handler, &pos);
        }
-       return obj->zo.properties;
+       return props;
 }
 /* }}} */
 
@@ -1040,7 +1040,6 @@ static void php_zip_object_free_storage(void *object TSRMLS_DC) /* {{{ */
 static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
 {
        ze_zip_object *intern;
-       zval *tmp;
        zend_object_value retval;
 
        intern = emalloc(sizeof(ze_zip_object));
@@ -1060,8 +1059,7 @@ static zend_object_value php_zip_object_new(zend_class_entry *class_type TSRMLS_
        intern->zo.ce = class_type;
 #endif
 
-       zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref,
-                                       (void *) &tmp, sizeof(zval *));
+       object_properties_init(&intern->zo, class_type);
 
        retval.handle = zend_objects_store_put(intern,
                                                NULL,