From f2df6a4a3ee7d1cff29dfc3326b50eb9d2818a05 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 15 Sep 2010 07:38:52 +0000 Subject: [PATCH] - Improved memory usage . 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. --- NEWS | 21 +++ UPGRADING.INTERNALS | 25 ++- Zend/zend.h | 22 ++- Zend/zend_API.c | 58 +++--- Zend/zend_API.h | 16 +- Zend/zend_closures.c | 2 +- Zend/zend_compile.c | 177 +++++++++--------- Zend/zend_compile.h | 79 +++++--- Zend/zend_execute.c | 2 +- Zend/zend_execute_API.c | 13 +- Zend/zend_globals.h | 6 +- Zend/zend_language_scanner.l | 2 + Zend/zend_object_handlers.c | 8 +- Zend/zend_opcode.c | 47 ++--- Zend/zend_vm_def.h | 6 +- Zend/zend_vm_execute.skl | 2 +- ext/pdo/pdo_dbh.c | 30 +-- ext/reflection/php_reflection.c | 38 ++-- .../ReflectionMethod_getModifiers_basic.phpt | 82 ++++---- ext/soap/soap.c | 1 - 20 files changed, 359 insertions(+), 278 deletions(-) diff --git a/NEWS b/NEWS index e0d9f31310..c6ce838f69 100644 --- a/NEWS +++ b/NEWS @@ -68,6 +68,27 @@ - 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. diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index d86dfc6f6b..9439874fab 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -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. diff --git a/Zend/zend.h b/Zend/zend.h index 0be3a1bcef..4de8b716c2 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -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" diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 11dd8c701e..bc25e7f2c6 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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) { diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 32f40b2b77..352a6088fd 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -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) \ diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 929e35a1b3..6e7954615a 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -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; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4720dec1e4..ff689f7af6 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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) || diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 29588a18ca..4e84a8b649 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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() \ @@ -52,6 +52,15 @@ 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 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 0a22ffa0dd..fc91fbc926 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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() \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 3220dfea57..f9c9bce99f 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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 (oplinelast -= 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; } /* }}} */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index dfc8075bdd..c66ef64c4d 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -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; diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 0783203cf5..f696f10385 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -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); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 4d05bef56e..87b68bd2b7 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index d33fe98ad2..3ea912f96d 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -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; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 9b274cc615..3485c14838 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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)) { diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 05584d6fb3..426f689795 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -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(); diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index f50df54d48..291ffdc44f 100755 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -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); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 798b1247c5..467b965ced 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -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) ? "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); diff --git a/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt b/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt index 02c7b9fa3e..72baa53fda 100644 --- a/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt +++ b/ext/reflection/tests/ReflectionMethod_getModifiers_basic.phpt @@ -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 diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 3c7650e195..2265575b58 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -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); -- 2.49.0