]> granicus.if.org Git - php/commitdiff
- Improved memory usage
authorDmitry Stogov <dmitry@php.net>
Wed, 15 Sep 2010 07:38:52 +0000 (07:38 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 15 Sep 2010 07:38:52 +0000 (07:38 +0000)
  . zend_function.pass_rest_by_reference is replaced by
    ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags
  . zend_function.return_reference is replaced by ZEND_ACC_RETURN_REFERENCE
    in zend_function.fn_flags
  . zend_arg_info.required_num_args removed. it was needed only for internal
    functions. Now the first arg_info for internal function (which has special
    meaning) is represented by zend_internal_function_info structure.
  . zend_op_array.size, size_var, size_literal, current_brk_cont,
    backpatch_count moved into CG(context), because they are used only during
    compilation.
  . zend_op_array.start_op is moved into EG(start_op), because it's used
    only for 'interactive' execution of single top-level op-array.
  . zend_op_array.done_pass_two is replaced by ZEND_ACC_DONE_PASS_TWO in
    zend_op_array.fn_flags.
  . op_array.vars array is trimmed (reallocated) during pass_two.
  . zend_class_entry.constants_updated is replaced by
     ZEND_ACC_CONSTANTS_UPDATED in zend_class_entry.ce_flags
  . the size of zend_class_entry is reduced by sharing the same memory space
    by different information for internal and user classes.
    See zend_class_inttry.info union.

20 files changed:
NEWS
UPGRADING.INTERNALS
Zend/zend.h
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_closures.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_language_scanner.l
Zend/zend_object_handlers.c
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.skl
ext/pdo/pdo_dbh.c
ext/reflection/php_reflection.c
ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt
ext/soap/soap.c

diff --git a/NEWS b/NEWS
index e0d9f31310f11fa5fe92f16b3027f3e66a881900..c6ce838f69ff23b8289212d89b4f353ea8e258a7 100644 (file)
--- a/NEWS
+++ b/NEWS
 - Changed session.entropy_file to default to /dev/urandom or /dev/arandom if
   either is present at compile time. (Rasmus)
 
+- Improved memory usage (Dmitry)
+  . zend_function.pass_rest_by_reference is replaced by
+    ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags
+  . zend_function.return_reference is replaced by ZEND_ACC_RETURN_REFERENCE
+    in zend_function.fn_flags
+  . zend_arg_info.required_num_args removed. it was needed only for internal
+    functions. Now the first arg_info for internal function (which has special
+    meaning) is represented by zend_internal_function_info structure.
+  . zend_op_array.size, size_var, size_literal, current_brk_cont,
+    backpatch_count moved into CG(context), because they are used only during
+    compilation.
+  . zend_op_array.start_op is moved into EG(start_op), because it's used
+    only for 'interactive' execution of single top-level op-array.
+  . zend_op_array.done_pass_two is replaced by ZEND_ACC_DONE_PASS_TWO in
+    zend_op_array.fn_flags.
+  . op_array.vars array is trimmed (reallocated) during pass_two.
+  . zend_class_entry.constants_updated is replaced by
+     ZEND_ACC_CONSTANTS_UPDATED in zend_class_entry.ce_flags
+  . the size of zend_class_entry is reduced by sharing the same memory space
+    by different information for internal and user classes.
+    See zend_class_inttry.info union. 
 - Improved CLI Interactive readline shell (Johannes)
   . Added cli.pager ini setting to set a pager for output.
   . Added cli.prompt ini settingto configure the shell prompt.
index d86dfc6f6b18f2abdca673ff57cc0c45ee7996c4..9439874fab0805e1a660f3d4b1df4052a2fd2917 100644 (file)
@@ -21,9 +21,32 @@ php_sys_lstat is an alias to lstat (when avaible). On Windows it is now
 available using php_sys_lstat. php_sys_stat and php_sys_lstat usage is recommended 
 instead of calling lstat directly, to ensure portability.
 
-       b. readlink support
+       c. readlink support
 
 readlink is now available on all platforms. On unix-like platform
 php_sys_readlink is an alias to readlink (when avaible). On Windows it is now 
 available using php_sys_readlink. php_sys_readlink usage is recommended 
 instead of calling readlink directly, to ensure portability.
+
+       d. layout of some core ZE structures (zend_op_array, zend_class_entry, ...)
+
+. zend_function.pass_rest_by_reference is replaced by
+  ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags
+. zend_function.return_reference is replaced by ZEND_ACC_RETURN_REFERENCE
+  in zend_function.fn_flags
+. zend_arg_info.required_num_args removed. it was needed only for internal
+  functions. Now the first arg_info for internal function (which has special
+  meaning) is represented by zend_internal_function_info structure.
+. zend_op_array.size, size_var, size_literal, current_brk_cont,
+  backpatch_count moved into CG(context), because they are used only during
+  compilation.
+. zend_op_array.start_op is moved into EG(start_op), because it's used
+  only for 'interactive' execution of single top-level op-array.
+. zend_op_array.done_pass_two is replaced by ZEND_ACC_DONE_PASS_TWO in
+  zend_op_array.fn_flags.
+. op_array.vars array is trimmed (reallocated) during pass_two.
+. zend_class_entry.constants_updated is replaced by
+  ZEND_ACC_CONSTANTS_UPDATED in zend_class_entry.ce_flags
+. the size of zend_class_entry is reduced by sharing the same memory space
+  by different information for internal and user classes.
+  See zend_class_inttry.info union. 
index 0be3a1bcef3d2af94e8aa1872f9075de065ca960..4de8b716c2e3ca6527f14d632bda9e0bf4fe8b19 100644 (file)
@@ -465,7 +465,6 @@ struct _zend_class_entry {
        zend_uint name_length;
        struct _zend_class_entry *parent;
        int refcount;
-       zend_bool constants_updated;
        zend_uint ce_flags;
 
        HashTable function_table;
@@ -476,7 +475,6 @@ struct _zend_class_entry {
        HashTable constants_table;
        int default_properties_count;
        int default_static_members_count;
-       const struct _zend_function_entry *builtin_functions;
 
        union _zend_function *constructor;
        union _zend_function *destructor;
@@ -511,13 +509,19 @@ struct _zend_class_entry {
        zend_trait_alias **trait_aliases;
        zend_trait_precedence **trait_precedences;
 
-       char *filename;
-       zend_uint line_start;
-       zend_uint line_end;
-       char *doc_comment;
-       zend_uint doc_comment_len;
-
-       struct _zend_module_entry *module;
+       union {
+               struct {
+                       char *filename;
+                       zend_uint line_start;
+                       zend_uint line_end;
+                       char *doc_comment;
+                       zend_uint doc_comment_len;
+               } user;
+               struct {
+                       const struct _zend_function_entry *builtin_functions;
+                       struct _zend_module_entry *module;
+               } internal;
+       } info;
 };
 
 #include "zend_stream.h"
index 11dd8c701e18971ca7de4e367acfbbc641eefe96..bc25e7f2c6a755fafd66c7ff0abb0006cd007113 100644 (file)
@@ -1015,7 +1015,7 @@ 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) && class_type->default_static_members_count)) {
+       if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!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;
@@ -1070,7 +1070,7 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
                }
 
                *scope = old_scope;
-               class_type->constants_updated = 1;
+               class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
        }
 }
 /* }}} */
@@ -1953,24 +1953,6 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
                internal_function->function_name = (char*)ptr->fname;
                internal_function->scope = scope;
                internal_function->prototype = NULL;
-               if (ptr->arg_info) {
-                       internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
-                       internal_function->num_args = ptr->num_args;
-                       /* Currently you cannot denote that the function can accept less arguments than num_args */
-                       if (ptr->arg_info[0].required_num_args == -1) {
-                               internal_function->required_num_args = ptr->num_args;
-                       } else {
-                               internal_function->required_num_args = ptr->arg_info[0].required_num_args;
-                       }
-                       internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
-                       internal_function->return_reference = ptr->arg_info[0].return_reference;
-               } else {
-                       internal_function->arg_info = NULL;
-                       internal_function->num_args = 0;
-                       internal_function->required_num_args = 0;
-                       internal_function->pass_rest_by_reference = 0;
-                       internal_function->return_reference = 0;
-               }
                if (ptr->flags) {
                        if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
                                if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
@@ -1983,6 +1965,32 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
                } else {
                        internal_function->fn_flags = ZEND_ACC_PUBLIC;
                }
+               if (ptr->arg_info) {
+                       zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
+                       
+                       internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
+                       internal_function->num_args = ptr->num_args;
+                       /* Currently you cannot denote that the function can accept less arguments than num_args */
+                       if (info->required_num_args == -1) {
+                               internal_function->required_num_args = ptr->num_args;
+                       } else {
+                               internal_function->required_num_args = info->required_num_args;
+                       }
+                       if (info->pass_rest_by_reference) {
+                               if (info->pass_rest_by_reference == ZEND_SEND_PREFER_REF) {
+                                       internal_function->fn_flags |= ZEND_ACC_PASS_REST_PREFER_REF;
+                               } else {
+                                       internal_function->fn_flags |= ZEND_ACC_PASS_REST_BY_REFERENCE;
+                               }
+                       }
+                       if (info->return_reference) {
+                               internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
+                       }
+               } else {
+                       internal_function->arg_info = NULL;
+                       internal_function->num_args = 0;
+                       internal_function->required_num_args = 0;
+               }
                if (ptr->flags & ZEND_ACC_ABSTRACT) {
                        if (scope) {
                                /* This is a class that must be abstract itself. Here we set the check info. */
@@ -2353,10 +2361,10 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
        class_entry->type = ZEND_INTERNAL_CLASS;
        zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
        class_entry->ce_flags = ce_flags;
-       class_entry->module = EG(current_module);
+       class_entry->info.internal.module = EG(current_module);
 
-       if (class_entry->builtin_functions) {
-               zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
+       if (class_entry->info.internal.builtin_functions) {
+               zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
        }
 
        zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
@@ -2712,15 +2720,13 @@ get_function_via_handler:
                        if (strict_class && ce_org->__call) {
                                fcc->function_handler = emalloc(sizeof(zend_internal_function));
                                fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
-                               fcc->function_handler->internal_function.module = ce_org->module;
+                               fcc->function_handler->internal_function.module = (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL;
                                fcc->function_handler->internal_function.handler = zend_std_call_user_call;
                                fcc->function_handler->internal_function.arg_info = NULL;
                                fcc->function_handler->internal_function.num_args = 0;
                                fcc->function_handler->internal_function.scope = ce_org;
                                fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
                                fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
-                               fcc->function_handler->internal_function.pass_rest_by_reference = 0;
-                               fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
                                call_via_handler = 1;
                                retval = 1;
                        } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
index 32f40b2b7765629757942bb183f118fffcb17e4f..352a6088fdf0bfc1968f50211d53dc70f298731b 100644 (file)
@@ -96,14 +96,14 @@ typedef struct _zend_fcall_info_cache {
 #define ZEND_NS_FALIAS(ns, name, alias, arg_info)              ZEND_NS_FENTRY(ns, name, ZEND_FN(alias), arg_info, 0)
 #define ZEND_NS_DEP_FALIAS(ns, name, alias, arg_info)  ZEND_NS_FENTRY(ns, name, ZEND_FN(alias), arg_info, ZEND_ACC_DEPRECATED)
 
-#define ZEND_ARG_INFO(pass_by_ref, name)                                                       { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
-#define ZEND_ARG_PASS_INFO(pass_by_ref)                                                                { NULL, 0, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
-#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_CLASS, allow_null, pass_by_ref, 0, 0 },
-#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref, 0, 0 },
-#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, allow_null, pass_by_ref, 0, 0 },
+#define ZEND_ARG_INFO(pass_by_ref, name)                                                       { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref},
+#define ZEND_ARG_PASS_INFO(pass_by_ref)                                                                { NULL, 0, NULL, 0, 0, 0, pass_by_ref},
+#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_CLASS, allow_null, pass_by_ref},
+#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref},
+#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, allow_null, pass_by_ref},
 #define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)      \
        static const zend_arg_info name[] = {                                                                                                                                           \
-               { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
+               { NULL, 0, NULL, required_num_args, 0, return_reference, pass_rest_by_reference},
 #define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference)      \
        ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1)
 #define ZEND_END_ARG_INFO()            };
@@ -173,7 +173,6 @@ typedef struct _zend_fcall_info_cache {
                        class_container.name = zend_strndup(cl_name, _len);     \
                }                                                                                                               \
                class_container.name_length = _len;                                             \
-               class_container.builtin_functions = functions;                  \
                class_container.constructor = NULL;                                             \
                class_container.destructor = NULL;                                              \
                class_container.clone = NULL;                                                   \
@@ -202,7 +201,8 @@ typedef struct _zend_fcall_info_cache {
                class_container.interfaces = NULL;                                              \
                class_container.get_iterator = NULL;                                    \
                class_container.iterator_funcs.funcs = NULL;                    \
-               class_container.module = NULL;                                                  \
+               class_container.info.internal.module = NULL;                    \
+               class_container.info.internal.builtin_functions = functions;    \
        }
 
 #define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \
index 929e35a1b3cff9cda7bc3ae40485777a9ea72757..6e7954615a3d9246119a0c7efae791a283c901d7 100644 (file)
@@ -129,7 +129,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zval *obj TSRMLS_DC) /* {
 
        invoke->common = closure->func.common;
        invoke->type = ZEND_INTERNAL_FUNCTION;
-       invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
+       invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & ZEND_ACC_RETURN_REFERENCE);
        invoke->internal_function.handler = ZEND_MN(Closure___invoke);
        invoke->internal_function.module = 0;
        invoke->internal_function.scope = zend_ce_closure;
index 4720dec1e462e3e0adb789272e58832afd3e41f8..ff689f7af6de096402466957d514d16cf64aa0f6 100644 (file)
@@ -41,7 +41,7 @@
 #define SET_NODE(target, src) do { \
                target ## _type = (src)->op_type; \
                if ((src)->op_type == IS_CONST) { \
-                       target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant); \
+                       target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant TSRMLS_CC); \
                } else { \
                        target = (src)->u.op; \
                } \
@@ -170,6 +170,16 @@ static void init_compiler_declarables(TSRMLS_D) /* {{{ */
 }
 /* }}} */
 
+void zend_init_compiler_context(TSRMLS_D) /* {{{ */
+{
+       CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
+       CG(context).vars_size = 0;
+       CG(context).literals_size = 0;
+       CG(context).current_brk_cont = -1;
+       CG(context).backpatch_count = 0;
+       CG(context).labels = NULL;
+}
+/* }}} */
 
 void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
 {
@@ -190,8 +200,7 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
        CG(has_bracketed_namespaces) = 0;
        CG(current_import) = NULL;
        init_compiler_declarables(TSRMLS_C);
-       zend_stack_init(&CG(labels_stack));
-       CG(labels) = NULL;
+       zend_stack_init(&CG(context_stack));
 
 #ifdef ZEND_MULTIBYTE
        CG(script_encoding_list) = NULL;
@@ -238,7 +247,7 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */
        zend_stack_destroy(&CG(list_stack));
        zend_hash_destroy(&CG(filenames_table));
        zend_llist_destroy(&CG(open_files));
-       zend_stack_destroy(&CG(labels_stack));
+       zend_stack_destroy(&CG(context_stack));
 
 #ifdef ZEND_MULTIBYTE
        if (CG(script_encoding_list)) {
@@ -317,9 +326,9 @@ static int lookup_cv(zend_op_array *op_array, char* name, int name_len TSRMLS_DC
        }
        i = op_array->last_var;
        op_array->last_var++;
-       if (op_array->last_var > op_array->size_var) {
-               op_array->size_var += 16; /* FIXME */
-               op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
+       if (op_array->last_var > CG(context).vars_size) {
+               CG(context).vars_size += 16; /* FIXME */
+               op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_compiled_variable));
        }
        op_array->vars[i].name = zend_new_interned_string(name, name_len + 1, 1 TSRMLS_CC);
        op_array->vars[i].name_len = name_len;
@@ -339,13 +348,13 @@ void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
 }
 /* }}} */
 
-int zend_add_literal(zend_op_array *op_array, const zval *zv) /* {{{ */
+int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
 {
        int i = op_array->last_literal;
        op_array->last_literal++;
-       if (i >= op_array->size_literal) {
-               op_array->size_literal += 16; /* FIXME */
-               op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->size_literal * sizeof(zend_literal));
+       if (i >= CG(context).literals_size) {
+               CG(context).literals_size += 16; /* FIXME */
+               op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
        }
        if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
                zval *z = (zval*)zv;
@@ -376,12 +385,12 @@ int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
-               ret = zend_add_literal(op_array, zv);
+               ret = zend_add_literal(op_array, zv TSRMLS_CC);
        }
        
        lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
        ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
-       lc_literal = zend_add_literal(CG(active_op_array), &c);
+       lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        CALCULATE_LITERAL_HASH(lc_literal);
 
        return ret;
@@ -402,19 +411,19 @@ int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
-               ret = zend_add_literal(op_array, zv);
+               ret = zend_add_literal(op_array, zv TSRMLS_CC);
        }
 
        lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
        ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
-       lc_literal = zend_add_literal(CG(active_op_array), &c);
+       lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        CALCULATE_LITERAL_HASH(lc_literal);
 
        ns_separator = (char *) zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv)) + 1;
        lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
        lc_name = zend_str_tolower_dup(ns_separator, lc_len);
        ZVAL_STRINGL(&c, lc_name, lc_len, 0);
-       lc_literal = zend_add_literal(CG(active_op_array), &c);
+       lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        CALCULATE_LITERAL_HASH(lc_literal);
 
        return ret;
@@ -435,7 +444,7 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
-               ret = zend_add_literal(op_array, zv);
+               ret = zend_add_literal(op_array, zv TSRMLS_CC);
        }
 
        if (Z_STRVAL_P(zv)[0] == '\\') {
@@ -446,7 +455,7 @@ int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_D
                lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), lc_len);
        }
        ZVAL_STRINGL(&c, lc_name, lc_len, 0);
-       lc_literal = zend_add_literal(CG(active_op_array), &c);
+       lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        CALCULATE_LITERAL_HASH(lc_literal);
 
        GET_CACHE_SLOT(ret);
@@ -468,7 +477,7 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
                /* we already have function name as last literal (do nothing) */
                ret = op_array->last_literal - 1;
        } else {
-               ret = zend_add_literal(op_array, zv);
+               ret = zend_add_literal(op_array, zv TSRMLS_CC);
        }
 
        /* skip leading '\\' */ 
@@ -491,13 +500,13 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
                tmp_name = estrndup(name, name_len);
                zend_str_tolower(tmp_name, ns_len);
                ZVAL_STRINGL(&c, tmp_name, name_len, 0);
-               tmp_literal = zend_add_literal(CG(active_op_array), &c);
+               tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
                CALCULATE_LITERAL_HASH(tmp_literal);
 
                /* lowercased namespace name & lowercased constant name */
                tmp_name = zend_str_tolower_dup(name, name_len);
                ZVAL_STRINGL(&c, tmp_name, name_len, 0);
-               tmp_literal = zend_add_literal(CG(active_op_array), &c);
+               tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
                CALCULATE_LITERAL_HASH(tmp_literal);
        }
 
@@ -513,13 +522,13 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
        /* original constant name */
        tmp_name = estrndup(name, name_len);
        ZVAL_STRINGL(&c, tmp_name, name_len, 0);
-       tmp_literal = zend_add_literal(CG(active_op_array), &c);
+       tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        CALCULATE_LITERAL_HASH(tmp_literal);
 
        /* lowercased constant name */
        tmp_name = zend_str_tolower_dup(name, name_len);
        ZVAL_STRINGL(&c, tmp_name, name_len, 0);
-       tmp_literal = zend_add_literal(CG(active_op_array), &c);
+       tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        CALCULATE_LITERAL_HASH(tmp_literal);
 
        return ret;
@@ -529,25 +538,25 @@ int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unq
 #define LITERAL_STRINGL(op, str, len, copy) do { \
                zval _c; \
                ZVAL_STRINGL(&_c, str, len, copy); \
-               op.constant = zend_add_literal(CG(active_op_array), &_c); \
+               op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
        } while (0)
 
 #define LITERAL_LONG(op, val) do { \
                zval _c; \
                ZVAL_LONG(&_c, val); \
-               op.constant = zend_add_literal(CG(active_op_array), &_c); \
+               op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
        } while (0)
 
 #define LITERAL_LONG_EX(op_array, op, val) do { \
                zval _c; \
                ZVAL_LONG(&_c, val); \
-               op.constant = zend_add_literal(op_array, &_c); \
+               op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
        } while (0)
 
 #define LITERAL_NULL(op) do { \
                zval _c; \
                INIT_ZVAL(      _c); \
-               op.constant = zend_add_literal(CG(active_op_array), &_c); \
+               op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
        } while (0)
 
 static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
@@ -1049,8 +1058,8 @@ static inline void do_begin_loop(TSRMLS_D) /* {{{ */
        zend_brk_cont_element *brk_cont_element;
        int parent;
 
-       parent = CG(active_op_array)->current_brk_cont;
-       CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
+       parent = CG(context).current_brk_cont;
+       CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
        brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
        brk_cont_element->start = get_next_op_number(CG(active_op_array));
        brk_cont_element->parent = parent;
@@ -1063,11 +1072,11 @@ static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{
                /* The start fileld is used to free temporary variables in case of exceptions.
                 * We won't try to free something of we don't have loop variable.
                 */
-               CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
+               CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
        }
-       CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
-       CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
-       CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
+       CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
+       CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
+       CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
 }
 /* }}} */
 
@@ -1539,9 +1548,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
        CG(interactive) = orig_interactive;
 
        op_array.function_name = name;
-       op_array.return_reference = return_reference;
+       if (return_reference) {
+               op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
+       }
        op_array.fn_flags |= fn_flags;
-       op_array.pass_rest_by_reference = 0;
 
        op_array.scope = is_method?CG(active_class_entry):NULL;
        op_array.prototype = NULL;
@@ -1555,6 +1565,9 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                        zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
                }
 
+               zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
+               zend_init_compiler_context(TSRMLS_C);
+
                if (fn_flags & ZEND_ACC_ABSTRACT) {
                        CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
                }
@@ -1676,13 +1689,15 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                opline->opcode = ZEND_DECLARE_FUNCTION;
                opline->op1_type = IS_CONST;
                build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
-               opline->op1.constant = zend_add_literal(CG(active_op_array), &key);
+               opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
                Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
                opline->op2_type = IS_CONST;
                LITERAL_STRINGL(opline->op2, lcname, name_len, 0);
                CALCULATE_LITERAL_HASH(opline->op2.constant);
                opline->extended_value = ZEND_DECLARE_FUNCTION;
                zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+               zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
+               zend_init_compiler_context(TSRMLS_C);
        }
 
        if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
@@ -1721,9 +1736,6 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                CG(doc_comment) = NULL;
                CG(doc_comment_len) = 0;
        }
-
-       zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
-       CG(labels) = NULL;
 }
 /* }}} */
 
@@ -2225,18 +2237,17 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
 
 void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
 {
-       zend_op_array *oparray = CG(active_op_array);
        zend_label dest;
 
-       if (!CG(labels)) {
-               ALLOC_HASHTABLE(CG(labels));
-               zend_hash_init(CG(labels), 4, NULL, NULL, 0);
+       if (!CG(context).labels) {
+               ALLOC_HASHTABLE(CG(context).labels);
+               zend_hash_init(CG(context).labels, 4, NULL, NULL, 0);
        }
 
-       dest.brk_cont = oparray->current_brk_cont;
-       dest.opline_num = get_next_op_number(oparray);
+       dest.brk_cont = CG(context).current_brk_cont;
+       dest.opline_num = get_next_op_number(CG(active_op_array));
 
-       if (zend_hash_add(CG(labels), Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
+       if (zend_hash_add(CG(context).labels, Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
                zend_error(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
        }
 
@@ -2256,8 +2267,8 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2
        } else {
                label = &CONSTANT_EX(op_array, opline->op2.constant);
        }
-       if (CG(labels) == NULL ||
-           zend_hash_find(CG(labels), Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
+       if (CG(context).labels == NULL ||
+           zend_hash_find(CG(context).labels, Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
 
            if (pass2) {
                CG(in_compilation) = 1;
@@ -2310,7 +2321,7 @@ void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
        opline->opcode = ZEND_GOTO;
-       opline->extended_value = CG(active_op_array)->current_brk_cont;
+       opline->extended_value = CG(context).current_brk_cont;
        SET_UNUSED(opline->op1);
        SET_NODE(opline->op2, label);
        zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
@@ -2319,18 +2330,16 @@ void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
 
 void zend_release_labels(TSRMLS_D) /* {{{ */
 {
-       if (CG(labels)) {
-               zend_hash_destroy(CG(labels));
-               FREE_HASHTABLE(CG(labels));
+       if (CG(context).labels) {
+               zend_hash_destroy(CG(context).labels);
+               FREE_HASHTABLE(CG(context).labels);
        }
-       if (!zend_stack_is_empty(&CG(labels_stack))) {
-               HashTable **pht;
+       if (!zend_stack_is_empty(&CG(context_stack))) {
+               zend_compiler_context *ctx;
 
-               zend_stack_top(&CG(labels_stack), (void**)&pht);
-               CG(labels) = *pht;
-               zend_stack_del_top(&CG(labels_stack));
-       } else {
-               CG(labels) = NULL;
+               zend_stack_top(&CG(context_stack), (void**)&ctx);
+               CG(context) = *ctx;
+               zend_stack_del_top(&CG(context_stack));
        }
 }
 /* }}} */
@@ -2611,7 +2620,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
        int start_op_number, end_op_number;
 
        if (do_end_vparse) {
-               if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
+               if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(expr)) {
                        zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
                } else {
                        zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
@@ -2636,7 +2645,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
 
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = (CG(active_op_array)->return_reference == ZEND_RETURN_REF) ? ZEND_RETURN_BY_REF : ZEND_RETURN;
+       opline->opcode = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) ? ZEND_RETURN_BY_REF : ZEND_RETURN;
 
        if (expr) {
                SET_NODE(opline->op1, expr);
@@ -2942,12 +2951,13 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
        }
 
        if (fe->common.type != ZEND_USER_FUNCTION
-               && proto->common.pass_rest_by_reference
-               && !fe->common.pass_rest_by_reference) {
+               && (proto->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) != 0
+               && (fe->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) == 0) {
                return 0;
        }
 
-       if (fe->common.return_reference != proto->common.return_reference) {
+       if ((fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) !=
+           (proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
                return 0;
        }
 
@@ -2976,7 +2986,7 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
                }
        }
 
-       if (proto->common.pass_rest_by_reference) {
+       if (proto->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) {
                for (i=proto->common.num_args; i < fe->common.num_args; i++) {
                        if (!fe->common.arg_info[i].pass_by_reference) {
                                return 0;
@@ -3543,7 +3553,6 @@ static void zend_traits_duplicate_function(zend_function *fe, char *newname TSRM
                }
        }
        fe->op_array.opcodes = opcode_copy;
-       fe->op_array.start_op = fe->op_array.opcodes;
        fe->op_array.function_name = newname;
 
        /* was setting it to fe which does not work since fe is stack allocated and not a stable address */
@@ -3570,9 +3579,9 @@ static void zend_traits_duplicate_function(zend_function *fe, char *newname TSRM
        fe->op_array.brk_cont_array = (zend_brk_cont_element*)estrndup((char*)fe->op_array.brk_cont_array, sizeof(zend_brk_cont_element) * fe->op_array.last_brk_cont);
   
        /* TODO: check whether there is something similar and whether that is ok */
-       literals_copy = (zend_literal*)emalloc(fe->op_array.size_literal * sizeof(zend_literal));
+       literals_copy = (zend_literal*)emalloc(fe->op_array.last_literal * sizeof(zend_literal));
   
-       for (i = 0; i < fe->op_array.size_literal; i++) {
+       for (i = 0; i < fe->op_array.last_literal; i++) {
                literals_copy[i] = fe->op_array.literals[i];
                zval_copy_ctor(&literals_copy[i].constant);
        }
@@ -4320,7 +4329,7 @@ void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
        opline->opcode = op;
-       opline->op1.opline_num = CG(active_op_array)->current_brk_cont;
+       opline->op1.opline_num = CG(context).current_brk_cont;
        SET_UNUSED(opline->op1);
        if (expr) {
                SET_NODE(opline->op2, expr);
@@ -4369,8 +4378,8 @@ void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
        }
 
        /* remember break/continue loop information */
-       CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
-       CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
+       CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
+       CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
 
        if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
                /* emit free for the switch condition*/
@@ -4525,8 +4534,8 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
        new_class_entry->name_length = Z_STRLEN(class_name->u.constant);
 
        zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
-       new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
-       new_class_entry->line_start = class_token->u.op.opline_num;
+       new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
+       new_class_entry->info.user.line_start = class_token->u.op.opline_num;
        new_class_entry->ce_flags |= class_token->EA;
 
        if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
@@ -4549,7 +4558,7 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        opline->op1_type = IS_CONST;
        build_runtime_defined_function_key(&key, lcname, new_class_entry->name_length TSRMLS_CC);
-       opline->op1.constant = zend_add_literal(CG(active_op_array), &key);
+       opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
        Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
        
        opline->op2_type = IS_CONST;
@@ -4572,8 +4581,8 @@ void zend_do_begin_class_declaration(const znode *class_token, znode *class_name
        GET_NODE(&CG(implementing_class), opline->result);
 
        if (CG(doc_comment)) {
-               CG(active_class_entry)->doc_comment = CG(doc_comment);
-               CG(active_class_entry)->doc_comment_len = CG(doc_comment_len);
+               CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
+               CG(active_class_entry)->info.user.doc_comment_len = CG(doc_comment_len);
                CG(doc_comment) = NULL;
                CG(doc_comment_len) = 0;
        }
@@ -4613,7 +4622,7 @@ void zend_do_end_class_declaration(const znode *class_token, const znode *parent
                }
        }
 
-       ce->line_end = zend_get_compiled_lineno(TSRMLS_C);
+       ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
        
        /* Check for traits and proceed like with interfaces.
         * The only difference will be a combined handling of them in the end.
@@ -6205,12 +6214,8 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
        dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
 
        ce->refcount = 1;
-       ce->constants_updated = 0;
        ce->ce_flags = 0;
 
-       ce->doc_comment = NULL;
-       ce->doc_comment_len = 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);
@@ -6233,6 +6238,8 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
 #endif
        } else {
                ce->static_members_table = ce->default_static_members_table;
+               ce->info.user.doc_comment = NULL;
+               ce->info.user.doc_comment_len = 0;
        }
 
        ce->default_properties_count = 0;
@@ -6261,12 +6268,14 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
                ce->traits = NULL;
                ce->trait_aliases = NULL;
                ce->trait_precedences = NULL;
-               ce->module = NULL;
                ce->serialize = NULL;
                ce->unserialize = NULL;
                ce->serialize_func = NULL;
                ce->unserialize_func = NULL;
-               ce->builtin_functions = NULL;
+               if (ce->type == ZEND_INTERNAL_CLASS) {
+                       ce->info.internal.module = NULL;
+                       ce->info.internal.builtin_functions = NULL;
+               }
        }
 }
 /* }}} */
@@ -6456,7 +6465,7 @@ void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{
                efree(c_ns_name);
        } else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
                   (*pce)->type == ZEND_USER_CLASS &&
-                  (*pce)->filename == CG(compiled_filename)) {
+                  (*pce)->info.user.filename == CG(compiled_filename)) {
                char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
 
                if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
index 29588a18ca909166d22ff192e82224b5d889f01e..4e84a8b6493e15d4faa6c5ea396f3568cd5edfc6 100644 (file)
@@ -36,8 +36,8 @@
 
 #define SET_UNUSED(op)  op ## _type = IS_UNUSED
 
-#define INC_BPC(op_array)      if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { ((op_array)->backpatch_count++); }
-#define DEC_BPC(op_array)      if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { ((op_array)->backpatch_count--); }
+#define INC_BPC(op_array)      if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count++); }
+#define DEC_BPC(op_array)      if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { (CG(context).backpatch_count--); }
 #define HANDLE_INTERACTIVE()  if (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) { execute_new_code(TSRMLS_C); }
 
 #define RESET_DOC_COMMENT()        \
 typedef struct _zend_op_array zend_op_array;
 typedef struct _zend_op zend_op;
 
+typedef struct _zend_compiler_context {
+       zend_uint  opcodes_size;
+       int        vars_size;
+       int        literals_size;
+       int        current_brk_cont;
+       int        backpatch_count;
+       HashTable *labels;
+} zend_compiler_context;
+
 typedef struct _zend_literal {
        zval       constant;
        zend_ulong hash_value;
@@ -171,6 +180,9 @@ typedef struct _zend_try_catch_element {
 #define ZEND_ACC_IMPLEMENT_INTERFACES 0x80000
 #define ZEND_ACC_IMPLEMENT_TRAITS        0x400000
 
+/* class constants updated */
+#define ZEND_ACC_CONSTANTS_UPDATED       0x100000
+
 /* user class has methods with static variables */
 #define ZEND_HAS_STATIC_IN_METHODS    0x800000
 
@@ -180,6 +192,12 @@ typedef struct _zend_try_catch_element {
 /* function flag for internal user call handlers __call, __callstatic */
 #define ZEND_ACC_CALL_VIA_HANDLER     0x200000
 
+#define ZEND_ACC_PASS_REST_BY_REFERENCE 0x1000000
+#define ZEND_ACC_PASS_REST_PREFER_REF  0x2000000
+
+#define ZEND_ACC_RETURN_REFERENCE              0x4000000
+#define ZEND_ACC_DONE_PASS_TWO                 0x8000000
+
 char *zend_visibility_string(zend_uint fn_flags);
 
 
@@ -203,10 +221,22 @@ typedef struct _zend_arg_info {
        zend_uchar type_hint;
        zend_bool allow_null;
        zend_bool pass_by_reference;
-       zend_bool return_reference;
-       int required_num_args;
 } zend_arg_info;
 
+/* the following structure repeats the layout of zend_arg_info,
+ * but its fields have different meaning. It's used as the first element of 
+ * arg_info array to define properties of internal functions.
+ */
+typedef struct _zend_internal_function_info {
+       const char *_name;
+       zend_uint _name_len;
+       const char *_class_name;
+       zend_uint required_num_args;
+       zend_uchar _type_hint;
+       zend_bool return_reference;
+       zend_bool pass_rest_by_reference;
+} zend_internal_function_info;
+
 typedef struct _zend_compiled_variable {
        char *name;
        int name_len;
@@ -223,25 +253,20 @@ struct _zend_op_array {
        zend_uint num_args;
        zend_uint required_num_args;
        zend_arg_info *arg_info;
-       zend_bool pass_rest_by_reference;
-       unsigned char return_reference;
        /* END of common elements */
 
-       zend_bool done_pass_two;
-
        zend_uint *refcount;
 
        zend_op *opcodes;
-       zend_uint last, size;
+       zend_uint last;
 
        zend_compiled_variable *vars;
-       int last_var, size_var;
+       int last_var;
 
        zend_uint T;
 
        zend_brk_cont_element *brk_cont_array;
        int last_brk_cont;
-       int current_brk_cont;
 
        zend_try_catch_element *try_catch_array;
        int last_try_catch;
@@ -249,9 +274,6 @@ struct _zend_op_array {
        /* static variables support */
        HashTable *static_variables;
 
-       zend_op *start_op;
-       int backpatch_count;
-
        zend_uint this_var;
 
        char *filename;
@@ -262,7 +284,7 @@ struct _zend_op_array {
        zend_uint early_binding; /* the linked list of delayed declarations */
 
        zend_literal *literals;
-       int last_literal, size_literal;
+       int last_literal;
 
        void **run_time_cache;
        int  last_cache_slot;
@@ -284,8 +306,6 @@ typedef struct _zend_internal_function {
        zend_uint num_args;
        zend_uint required_num_args;
        zend_arg_info *arg_info;
-       zend_bool pass_rest_by_reference;
-       unsigned char return_reference;
        /* END of common elements */
 
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
@@ -306,8 +326,6 @@ typedef union _zend_function {
                zend_uint num_args;
                zend_uint required_num_args;
                zend_arg_info *arg_info;
-               zend_bool pass_rest_by_reference;
-               unsigned char return_reference;
        } common;
 
        zend_op_array op_array;
@@ -374,6 +392,7 @@ BEGIN_EXTERN_C()
 void init_compiler(TSRMLS_D);
 void shutdown_compiler(TSRMLS_D);
 void zend_init_compiler_data_structures(TSRMLS_D);
+void zend_init_compiler_context(TSRMLS_D);
 
 extern ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
 extern ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
@@ -602,6 +621,7 @@ void zend_release_labels(TSRMLS_D);
 ZEND_API void function_add_ref(zend_function *function);
 
 #define INITIAL_OP_ARRAY_SIZE 64
+#define INITIAL_INTERACTIVE_OP_ARRAY_SIZE 8192
 
 
 /* helper functions in zend_language_scanner.l */
@@ -662,7 +682,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len);
 
 int zendlex(znode *zendlval TSRMLS_DC);
 
-int zend_add_literal(zend_op_array *op_array, const zval *zv);
+int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
 
 /* BEGIN: OPCODES */
 
@@ -766,22 +786,21 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv);
 #define ZEND_SEND_BY_REF     1
 #define ZEND_SEND_PREFER_REF 2
 
-#define ARG_SEND_TYPE(zf, arg_num)                                                                                             \
-       ((zf) ?                                                                     \
-        ((((zend_function*)(zf))->common.arg_info &&                               \
-          arg_num<=((zend_function*)(zf))->common.num_args) ?                      \
-         ((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference :   \
-         ((zend_function *)(zf))->common.pass_rest_by_reference) :                 \
-        ZEND_SEND_BY_VAL)      
+#define CHECK_ARG_SEND_TYPE(zf, arg_num, m1, m2)                                                                                       \
+       ((zf) &&                                                                                                                                                                \
+         ((((zend_function*)(zf))->common.arg_info &&                                                                                  \
+           arg_num <= ((zend_function*)(zf))->common.num_args) ?                                                               \
+          (((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference & (m1)) :             \
+       (((zend_function *)(zf))->common.fn_flags & (m2))))
 
 #define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
-       (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_BY_REF)
+       CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF, ZEND_ACC_PASS_REST_BY_REFERENCE)
 
 #define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
-       (ARG_SEND_TYPE(zf, arg_num) & (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF))
+       CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF, ZEND_ACC_PASS_REST_BY_REFERENCE|ZEND_ACC_PASS_REST_PREFER_REF)
 
 #define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
-       (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_PREFER_REF)
+       CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_PREFER_REF, ZEND_ACC_PASS_REST_PREFER_REF)
 
 #define ZEND_RETURN_VAL 0
 #define ZEND_RETURN_REF 1
index 0a22ffa0ddc04778beaad459f34b25d84da8df84..fc91fbc926562c96658b569eb6382e1bb28bdd42 100644 (file)
@@ -1476,7 +1476,7 @@ ZEND_API opcode_handler_t *zend_opcode_handlers;
 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
 {
        zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr;
-       ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, execute_data_ptr->function_state.function->common.return_reference?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
+       ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
 }
 
 #define ZEND_VM_NEXT_OPCODE() \
index 3220dfea57b2ffc97c28c766840f688246227ebc..f9c9bce99f2cb963fc4023f89c86f2c6c5a54b5c 100644 (file)
@@ -194,6 +194,7 @@ void init_executor(TSRMLS_D) /* {{{ */
        EG(active_op_array) = NULL;
 
        EG(active) = 1;
+       EG(start_op) = NULL;
 }
 /* }}} */
 
@@ -1256,7 +1257,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
        int orig_interactive;
 
        if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
-               || CG(active_op_array)->backpatch_count>0
+               || CG(context).backpatch_count>0
                || CG(active_op_array)->function_name
                || CG(active_op_array)->type!=ZEND_USER_FUNCTION) {
                return;
@@ -1265,14 +1266,14 @@ void execute_new_code(TSRMLS_D) /* {{{ */
        ret_opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        ret_opline->opcode = ZEND_RETURN;
        ret_opline->op1_type = IS_CONST;
-       ret_opline->op1.constant = zend_add_literal(CG(active_op_array), &EG(uninitialized_zval));
+       ret_opline->op1.constant = zend_add_literal(CG(active_op_array), &EG(uninitialized_zval) TSRMLS_CC);
        SET_UNUSED(ret_opline->op2);
 
-       if (!CG(active_op_array)->start_op) {
-               CG(active_op_array)->start_op = CG(active_op_array)->opcodes;
+       if (!EG(start_op)) {
+               EG(start_op) = CG(active_op_array)->opcodes;
        }
 
-       opline=CG(active_op_array)->start_op;
+       opline=EG(start_op);
        end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
 
        while (opline<end) {
@@ -1317,7 +1318,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
        }
 
        CG(active_op_array)->last -= 1; /* get rid of that ZEND_RETURN */
-       CG(active_op_array)->start_op = CG(active_op_array)->opcodes+CG(active_op_array)->last;
+       EG(start_op) = CG(active_op_array)->opcodes+CG(active_op_array)->last;
 }
 /* }}} */
 
index dfc8075bdddb94da781cd7878fe96a53af2252f4..c66ef64c4d01b95fb3f073c4d09215966c72179d 100644 (file)
@@ -139,8 +139,8 @@ struct _zend_compiler_globals {
        zend_bool  in_namespace;
        zend_bool  has_bracketed_namespaces;
 
-       HashTable *labels;
-       zend_stack labels_stack;
+       zend_compiler_context context;
+       zend_stack context_stack;
 
        /* interned strings */
        char *interned_strings_start;
@@ -265,6 +265,8 @@ struct _zend_executor_globals {
 
        zend_bool active; 
 
+       zend_op *start_op;
+
        void *saved_fpu_cw_ptr;
 #if XPFPA_HAVE_CW
        XPFPA_CW_DATATYPE saved_fpu_cw;
index 0783203cf53c098e864996e7ae5648bb6e81330b..f696f10385663ef3c88dd0019a9641fdc25bf4fe 100644 (file)
@@ -351,6 +351,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSR
                init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                CG(in_compilation) = 1;
                CG(active_op_array) = op_array;
+               zend_init_compiler_context(TSRMLS_C);
                compiler_result = zendparse(TSRMLS_C);
                zend_do_return(&retval_znode, 0 TSRMLS_CC);
                CG(in_compilation) = original_in_compilation;
@@ -515,6 +516,7 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
                init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                CG(interactive) = orig_interactive;
                CG(active_op_array) = op_array;
+               zend_init_compiler_context(TSRMLS_C);
                BEGIN(ST_IN_SCRIPTING);
                compiler_result = zendparse(TSRMLS_C);
 
index 4d05bef56e71e95fa9a6b12033665fd94c6e3814..87b68bd2b7357d1c584c0a6c471b6bca6ab5e7ab 100644 (file)
@@ -938,15 +938,13 @@ static inline union _zend_function *zend_get_user_call_function(zend_class_entry
 {
        zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
        call_user_call->type = ZEND_INTERNAL_FUNCTION;
-       call_user_call->module = ce->module;
+       call_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
        call_user_call->handler = zend_std_call_user_call;
        call_user_call->arg_info = NULL;
        call_user_call->num_args = 0;
        call_user_call->scope = ce;
        call_user_call->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
        call_user_call->function_name = estrndup(method_name, method_len);
-       call_user_call->pass_rest_by_reference = 0;
-       call_user_call->return_reference = ZEND_RETURN_VALUE;
 
        return (union _zend_function *)call_user_call;
 }
@@ -1083,15 +1081,13 @@ static inline union _zend_function *zend_get_user_callstatic_function(zend_class
 {
        zend_internal_function *callstatic_user_call = emalloc(sizeof(zend_internal_function));
        callstatic_user_call->type     = ZEND_INTERNAL_FUNCTION;
-       callstatic_user_call->module   = ce->module;
+       callstatic_user_call->module   = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL;
        callstatic_user_call->handler  = zend_std_callstatic_user_call;
        callstatic_user_call->arg_info = NULL;
        callstatic_user_call->num_args = 0;
        callstatic_user_call->scope    = ce;
        callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER;
        callstatic_user_call->function_name = estrndup(method_name, method_len);
-       callstatic_user_call->pass_rest_by_reference = 0;
-       callstatic_user_call->return_reference       = ZEND_RETURN_VALUE;
 
        return (zend_function *)callstatic_user_call;
 }
index d33fe98ad20d48d39672b1d450ff881568c789fd..3ea912f96df73b29fa486c4a9ad6e12b49c3bd55 100644 (file)
@@ -43,31 +43,28 @@ static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend
        }
 }
 
-static void op_array_alloc_ops(zend_op_array *op_array)
+static void op_array_alloc_ops(zend_op_array *op_array, zend_uint size)
 {
-       op_array->opcodes = erealloc(op_array->opcodes, (op_array->size)*sizeof(zend_op));
+       op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op));
 }
 
 void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size TSRMLS_DC)
 {
        op_array->type = type;
 
-       op_array->backpatch_count = 0;
        if (CG(interactive)) {
                /* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants
                 * will become invalid
                 */
-               initial_ops_size = 8192;
+               initial_ops_size = INITIAL_INTERACTIVE_OP_ARRAY_SIZE;
        }
 
        op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint));
        *op_array->refcount = 1;
-       op_array->size = initial_ops_size;
        op_array->last = 0;
        op_array->opcodes = NULL;
-       op_array_alloc_ops(op_array);
+       op_array_alloc_ops(op_array, initial_ops_size);
 
-       op_array->size_var = 0;
        op_array->last_var = 0;
        op_array->vars = NULL;
 
@@ -87,23 +84,16 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
        op_array->brk_cont_array = NULL;
        op_array->try_catch_array = NULL;
        op_array->last_brk_cont = 0;
-       op_array->current_brk_cont = -1;
 
        op_array->static_variables = NULL;
        op_array->last_try_catch = 0;
 
-       op_array->return_reference = 0;
-       op_array->done_pass_two = 0;
-
        op_array->this_var = -1;
 
-       op_array->start_op = NULL;
-
        op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0;
 
        op_array->early_binding = -1;
 
-       op_array->size_literal = 0;
        op_array->last_literal = 0;
        op_array->literals = NULL;
 
@@ -309,8 +299,8 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        if (ce->num_interfaces > 0 && ce->interfaces) {
                                efree(ce->interfaces);
                        }
-                       if (ce->doc_comment) {
-                               efree(ce->doc_comment);
+                       if (ce->info.user.doc_comment) {
+                               efree(ce->info.user.doc_comment);
                        }
                        
                        _destroy_zend_class_traits_info(ce);
@@ -345,9 +335,6 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        if (ce->num_interfaces > 0) {
                                free(ce->interfaces);
                        }
-                       if (ce->doc_comment) {
-                               free(ce->doc_comment);
-                       }
                        free(ce);
                        break;
        }
@@ -410,7 +397,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
        if (op_array->try_catch_array) {
                efree(op_array->try_catch_array);
        }
-       if (op_array->done_pass_two) {
+       if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
                zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC);
        }
        if (op_array->arg_info) {
@@ -436,15 +423,15 @@ zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC)
        zend_uint next_op_num = op_array->last++;
        zend_op *next_op;
 
-       if (next_op_num >= op_array->size) {
+       if (next_op_num >= CG(context).opcodes_size) {
                if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) {
                        /* we messed up */
                        zend_printf("Ran out of opcode space!\n"
                                                "You should probably consider writing this huge script into a file!\n");
                        zend_bailout();
                }
-               op_array->size *= 4;
-               op_array_alloc_ops(op_array);
+               CG(context).opcodes_size *= 4;
+               op_array_alloc_ops(op_array, CG(context).opcodes_size);
        }
        
        next_op = &(op_array->opcodes[next_op_num]);
@@ -510,13 +497,17 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
                zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC);
        }
 
-       if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && op_array->size != op_array->last) {
+       if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) {
+               op_array->vars = (zend_compiled_variable *) erealloc(op_array->vars, sizeof(zend_compiled_variable)*op_array->last_var);
+               CG(context).vars_size = op_array->last_var;
+       }
+       if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) {
                op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last);
-               op_array->size = op_array->last;
+               CG(context).opcodes_size = op_array->last;
        }
-       if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && op_array->size_literal != op_array->last_literal) {
+       if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) {
                op_array->literals = (zend_literal*)erealloc(op_array->literals, sizeof(zend_literal) * op_array->last_literal);
-               op_array->size_literal = op_array->last_literal;
+               CG(context).literals_size = op_array->last_literal;
        }
 
        opline = op_array->opcodes;
@@ -549,7 +540,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
                opline++;
        }
 
-       op_array->done_pass_two = 1;
+       op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
        return 0;
 }
 
index 9b274cc615d6b149ee1516c81e4061a78aff4a4b..3485c14838121ad3ad88dad8d9a4eada756bbd5d 100644 (file)
@@ -2578,7 +2578,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                MAKE_STD_ZVAL(ret->var.ptr);
                ZVAL_NULL(ret->var.ptr);
                ret->var.ptr_ptr = &ret->var.ptr;
-               ret->var.fcall_returned_reference = fbc->common.return_reference;
+               ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
 
                if (fbc->common.arg_info) {
                        zend_uint i=0;
@@ -2593,7 +2593,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
 
                if (!zend_execute_internal) {
                        /* saves one function call if zend_execute_internal is not used */
-                       fbc->internal_function.handler(opline->extended_value, ret->var.ptr, fbc->common.return_reference ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+                       fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
                } else {
                        zend_execute_internal(EXECUTE_DATA, RETURN_VALUE_USED(opline) TSRMLS_CC);
                }
@@ -2612,7 +2612,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                        ret->var.ptr = NULL;
                        EG(return_value_ptr_ptr) = &ret->var.ptr;
                        ret->var.ptr_ptr = &ret->var.ptr;
-                       ret->var.fcall_returned_reference = fbc->common.return_reference;
+                       ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
                }
 
                if (EXPECTED(zend_execute == execute)) {
index 05584d6fb3af5fa3033a4c870a581ab2f305d9c2..426f689795fc94780ed01a14ea82f836159b93ba 100644 (file)
@@ -55,7 +55,7 @@ zend_vm_enter:
                }
        }
 
-       EX(opline) = op_array->start_op ? op_array->start_op : op_array->opcodes;
+       EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
        EG(opline_ptr) = &EX(opline);
        LOAD_OPLINE();
 
index f50df54d48b48fceff4f0a188bd70f1c19d8e7db..291ffdc44f3280e96fe97fe50b8cdfc6e38115a2 100755 (executable)
@@ -1308,27 +1308,35 @@ int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
                ifunc->function_name = (char*)funcs->fname;
                ifunc->scope = dbh->std.ce;
                ifunc->prototype = NULL;
+               if (funcs->flags) {
+                       ifunc->fn_flags = funcs->flags;
+               } else {
+                       ifunc->fn_flags = ZEND_ACC_PUBLIC;
+               }
                if (funcs->arg_info) {
+                       zend_internal_function_info *info = (zend_internal_function_info*)funcs->arg_info;
+
                        ifunc->arg_info = (zend_arg_info*)funcs->arg_info + 1;
                        ifunc->num_args = funcs->num_args;
-                       if (funcs->arg_info[0].required_num_args == -1) {
+                       if (info->required_num_args == -1) {
                                ifunc->required_num_args = funcs->num_args;
                        } else {
-                               ifunc->required_num_args = funcs->arg_info[0].required_num_args;
+                               ifunc->required_num_args = info->required_num_args;
+                       }
+                       if (info->pass_rest_by_reference) {
+                               if (info->pass_rest_by_reference == ZEND_SEND_PREFER_REF) {
+                                       ifunc->fn_flags |= ZEND_ACC_PASS_REST_PREFER_REF;
+                               } else {
+                                       ifunc->fn_flags |= ZEND_ACC_PASS_REST_BY_REFERENCE;
+                               }
+                       }
+                       if (info->return_reference) {
+                               ifunc->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
                        }
-                       ifunc->pass_rest_by_reference = funcs->arg_info[0].pass_by_reference;
-                       ifunc->return_reference = funcs->arg_info[0].return_reference;
                } else {
                        ifunc->arg_info = NULL;
                        ifunc->num_args = 0;
                        ifunc->required_num_args = 0;
-                       ifunc->pass_rest_by_reference = 0;
-                       ifunc->return_reference = 0;
-               }
-               if (funcs->flags) {
-                       ifunc->fn_flags = funcs->flags;
-               } else {
-                       ifunc->fn_flags = ZEND_ACC_PUBLIC;
                }
                namelen = strlen(funcs->fname);
                lc_name = emalloc(namelen+1);
index 798b1247c5ff3507a6d8a3035c94ae0bd40cf3c9..467b965ced5e23f9653a791e80ab5bdbab5e14eb 100644 (file)
@@ -356,8 +356,8 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
        string_printf(&sub_indent, "%s    ", indent);
 
        /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
-       if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
-               string_printf(str, "%s%s", indent, ce->doc_comment);
+       if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
+               string_printf(str, "%s%s", indent, ce->info.user.doc_comment);
                string_write(str, "\n", 1);
        }
 
@@ -373,8 +373,8 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
                string_printf(str, "%s%s [ ", indent, kind);
        }
        string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
-       if (ce->module) {
-               string_printf(str, ":%s", ce->module->name);
+       if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
+               string_printf(str, ":%s", ce->info.internal.module->name);
        }
        string_printf(str, "> ");
        if (ce->get_iterator != NULL) {
@@ -414,8 +414,8 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
 
        /* The information where a class is declared is only available for user classes */
        if (ce->type == ZEND_USER_CLASS) {
-               string_printf(str, "%s  @@ %s %d-%d\n", indent, ce->filename,
-                                               ce->line_start, ce->line_end);
+               string_printf(str, "%s  @@ %s %d-%d\n", indent, ce->info.user.filename,
+                                               ce->info.user.line_start, ce->info.user.line_end);
        }
 
        /* Constants */
@@ -891,7 +891,7 @@ static void _function_string(string *str, zend_function *fptr, zend_class_entry
                string_printf(str, "function ");
        }
 
-       if (fptr->op_array.return_reference) {
+       if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
                string_printf(str, "&");
        }
        string_printf(str, "%s ] {\n", fptr->common.function_name);
@@ -997,7 +997,7 @@ static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_arg
        struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
        int *num_classes = va_arg(args, int*);
 
-       if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+       if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
                string_printf(str, "\n");
                _class_string(str, *pce, NULL, indent TSRMLS_CC);
                (*num_classes)++;
@@ -1940,7 +1940,7 @@ ZEND_METHOD(reflection_function, returnsReference)
        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
        GET_REFLECTION_OBJECT_PTR(fptr);
 
-       RETURN_BOOL(fptr->op_array.return_reference);
+       RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
 }
 /* }}} */
 
@@ -3521,7 +3521,7 @@ ZEND_METHOD(reflection_class, getFileName)
        }
        GET_REFLECTION_OBJECT_PTR(ce);
        if (ce->type == ZEND_USER_CLASS) {
-               RETURN_STRING(ce->filename, 1);
+               RETURN_STRING(ce->info.user.filename, 1);
        }
        RETURN_FALSE;
 }
@@ -3539,7 +3539,7 @@ ZEND_METHOD(reflection_class, getStartLine)
        }
        GET_REFLECTION_OBJECT_PTR(ce);
        if (ce->type == ZEND_USER_FUNCTION) {
-               RETURN_LONG(ce->line_start);
+               RETURN_LONG(ce->info.user.line_start);
        }
        RETURN_FALSE;
 }
@@ -3557,7 +3557,7 @@ ZEND_METHOD(reflection_class, getEndLine)
        }
        GET_REFLECTION_OBJECT_PTR(ce);
        if (ce->type == ZEND_USER_CLASS) {
-               RETURN_LONG(ce->line_end);
+               RETURN_LONG(ce->info.user.line_end);
        }
        RETURN_FALSE;
 }
@@ -3574,8 +3574,8 @@ ZEND_METHOD(reflection_class, getDocComment)
                return;
        }
        GET_REFLECTION_OBJECT_PTR(ce);
-       if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
-               RETURN_STRINGL(ce->doc_comment, ce->doc_comment_len, 1);
+       if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
+               RETURN_STRINGL(ce->info.user.doc_comment, ce->info.user.doc_comment_len, 1);
        }
        RETURN_FALSE;
 }
@@ -4548,8 +4548,8 @@ ZEND_METHOD(reflection_class, getExtension)
        METHOD_NOTSTATIC(reflection_class_ptr);
        GET_REFLECTION_OBJECT_PTR(ce);
 
-       if (ce->module) {
-               reflection_extension_factory(return_value, ce->module->name TSRMLS_CC);
+       if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
+               reflection_extension_factory(return_value, ce->info.internal.module->name TSRMLS_CC);
        }
 }
 /* }}} */
@@ -4568,8 +4568,8 @@ ZEND_METHOD(reflection_class, getExtensionName)
        METHOD_NOTSTATIC(reflection_class_ptr);
        GET_REFLECTION_OBJECT_PTR(ce);
 
-       if (ce->module) {
-               RETURN_STRING(ce->module->name, 1);
+       if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
+               RETURN_STRING(ce->info.internal.module->name, 1);
        } else {
                RETURN_FALSE;
        }
@@ -5271,7 +5271,7 @@ static int add_extension_class(zend_class_entry **pce TSRMLS_DC, int num_args, v
        struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
        int add_reflection_class = va_arg(args, int);
 
-       if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+       if (((*pce)->type == ZEND_INTERNAL_CLASS) && (*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name, module->name)) {
                if (add_reflection_class) {
                        ALLOC_ZVAL(zclass);
                        zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
index 02c7b9fa3e3ef41b986d3dfe2cf9954229090a9a..72baa53fda004e8d7e82ef0c3b88e4fab59bb1fc 100644 (file)
@@ -9,7 +9,7 @@ function reflectMethodModifiers($class) {
 
     foreach ($methodArray as $method) {
         echo "Modifiers for method $method->class::$method->name():\n";
-        var_dump($method->getModifiers());
+        printf("0x%08x\n", $method->getModifiers());
         echo "\n\n";
     }
 }
@@ -82,161 +82,161 @@ $a->getModifiers(1);
 $a = new ReflectionMethod('ReflectionMethod::getModifiers');
 
 echo "\nReflectionMethod::getModifiers() modifiers:\n";
-var_dump($a->getModifiers());
+printf("0x%08x\n", $a->getModifiers());
 
 ?>
 --EXPECTF--
 Modifiers for method TestClass::foo():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::stat():
-int(257)
+0x08000101
 
 
 Modifiers for method TestClass::priv():
-int(66560)
+0x08010400
 
 
 Modifiers for method TestClass::prot():
-int(66048)
+0x08010200
 
 
 Modifiers for method TestClass::fin():
-int(65796)
+0x08010104
 
 
 Modifiers for method TestClass::__destruct():
-int(16640)
+0x08004100
 
 
 Modifiers for method TestClass::__call():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__clone():
-int(33024)
+0x08008100
 
 
 Modifiers for method TestClass::__get():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__set():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__unset():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__isset():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__tostring():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__sleep():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::__wakeup():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::__set_state():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::__autoload():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::foo():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::stat():
-int(257)
+0x08000101
 
 
 Modifiers for method TestClass::priv():
-int(66560)
+0x08010400
 
 
 Modifiers for method TestClass::prot():
-int(66048)
+0x08010200
 
 
 Modifiers for method TestClass::fin():
-int(65796)
+0x08010104
 
 
 Modifiers for method TestClass::__destruct():
-int(16640)
+0x08004100
 
 
 Modifiers for method TestClass::__call():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__clone():
-int(33024)
+0x08008100
 
 
 Modifiers for method TestClass::__get():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__set():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__unset():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__isset():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__tostring():
-int(256)
+0x08000100
 
 
 Modifiers for method TestClass::__sleep():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::__wakeup():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::__set_state():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestClass::__autoload():
-int(65792)
+0x08010100
 
 
 Modifiers for method TestInterface::int():
-int(258)
+0x08000102
 
 
 Modifiers for method TestInterface::__clone():
-int(258)
+0x08000102
 
 
 Modifiers for method AbstractClass::foo():
-int(65794)
+0x08010102
 
 
 Wrong number of params:
 
-Warning: ReflectionMethod::getModifiers() expects exactly 0 parameters, 1 given in %s on line %d
+Warning: ReflectionMethod::getModifiers() expects exactly 0 parameters, 1 given in %sReflectionMethod_getModifiers_basic.php on line %d
 
 ReflectionMethod::getModifiers() modifiers:
-int(256)
+0x00000100
index 3c7650e195301ef160b5e06ab6ab6c3144c146a1..2265575b58fa8f8e89d8c336f8d8a87076356585 100644 (file)
@@ -703,7 +703,6 @@ PHP_MINIT_FUNCTION(soap)
                fe.prototype = NULL;
                fe.num_args = 2;
                fe.arg_info = NULL;
-               fe.pass_rest_by_reference = 0;
 
                INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
                        (zend_function *)&fe, NULL, NULL);