- 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.
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.
zend_uint name_length;
struct _zend_class_entry *parent;
int refcount;
- zend_bool constants_updated;
zend_uint ce_flags;
HashTable function_table;
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;
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"
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;
}
*scope = old_scope;
- class_type->constants_updated = 1;
+ class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
}
}
/* }}} */
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) {
} 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. */
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);
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) {
#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() };
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; \
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) \
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;
#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; \
} \
}
/* }}} */
+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) /* {{{ */
{
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;
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)) {
}
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;
}
/* }}} */
-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;
/* 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;
/* 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;
/* 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] == '\\') {
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);
/* 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 '\\' */
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);
}
/* 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;
#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) /* {{{ */
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;
/* 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;
}
/* }}} */
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;
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;
}
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) {
CG(doc_comment) = NULL;
CG(doc_comment_len) = 0;
}
-
- zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
- CG(labels) = NULL;
}
/* }}} */
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));
}
} 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;
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);
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));
}
}
/* }}} */
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);
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);
}
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;
}
}
}
- 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;
}
}
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 */
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);
}
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);
}
/* 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*/
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) {
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;
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;
}
}
}
- 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.
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);
#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;
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;
+ }
}
}
/* }}} */
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) ||
#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;
#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
/* 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);
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;
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;
/* static variables support */
HashTable *static_variables;
- zend_op *start_op;
- int backpatch_count;
-
zend_uint this_var;
char *filename;
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;
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);
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;
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);
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 */
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 */
#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
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() \
EG(active_op_array) = NULL;
EG(active) = 1;
+ EG(start_op) = NULL;
}
/* }}} */
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;
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) {
}
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;
}
/* }}} */
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;
zend_bool active;
+ zend_op *start_op;
+
void *saved_fpu_cw_ptr;
#if XPFPA_HAVE_CW
XPFPA_CW_DATATYPE saved_fpu_cw;
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;
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);
{
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;
}
{
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;
}
}
}
-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;
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;
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);
if (ce->num_interfaces > 0) {
free(ce->interfaces);
}
- if (ce->doc_comment) {
- free(ce->doc_comment);
- }
free(ce);
break;
}
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) {
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]);
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;
opline++;
}
- op_array->done_pass_two = 1;
+ op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return 0;
}
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;
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);
}
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)) {
}
}
- 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();
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);
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);
}
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) {
/* 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 */
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);
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)++;
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);
}
/* }}} */
}
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;
}
}
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;
}
}
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;
}
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;
}
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);
}
}
/* }}} */
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;
}
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);
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";
}
}
$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
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);