Hi,
The attached patch modifies internal ZE data structures.
It gives 4% less heap memory usage on waiting PHP process (2210KB
instead of 2304KB) and up to 7% improvement on applications with many
classes (ZendFramework benchmark uses 17.7M instead of 19M). It also
makes small speedup on some big applications with opcode caches, because
of less memory transfer.
The patch performs the following optimizations:
1) zend_function.pass_rest_by_reference is replaced by
ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags
2) zend_function.return_reference is replaced by
ZEND_ACC_RETURN_REFERENCE in zend_function.fn_flags
3) 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.
4) zend_op_array.size, size_var, size_literal, current_brk_cont,
backpatch_count moved into CG(context), because they are used only
during compilation.
5) 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.
6) zend_op_array.done_pass_two is replaced by ZEND_ACC_DONE_PASS_TWO in
zend_op_array.fn_flags.
7) the sise of op_array.vars is reduced during pass_two.
8) zend_class_entry.constants_updated is replaced by
ZEND_ACC_CONSTANTS_UPDATED in zend_class_entry.ce_flags
9) 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.
Of course the patch will affect some extensions (e.g. APC and xdebug),
but it shouldn't be difficult to fix them.
I'm going to commit the patch by the end of this week in case of no
objections. I'll also add corresponding notes into UPGRADING.INTERNALS.
Thanks. Dmitry.
Index: ext/soap/soap.c
===================================================================
--- ext/soap/soap.c (revision 303306)
+++ ext/soap/soap.c (working copy)
@@ -703,7 +703,6 @@
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);
Index: ext/pdo/pdo_dbh.c
===================================================================
--- ext/pdo/pdo_dbh.c (revision 303306)
+++ ext/pdo/pdo_dbh.c (working copy)
@@ -1308,28 +1308,36 @@
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;
}
- ifunc->pass_rest_by_reference =
funcs->arg_info[0].pass_by_reference;
- ifunc->return_reference =
funcs->arg_info[0].return_reference;
+ 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;
+ }
} 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);
zend_str_tolower_copy(lc_name, funcs->fname, namelen);
Index: ext/reflection/php_reflection.c
===================================================================
--- ext/reflection/php_reflection.c (revision 303306)
+++ ext/reflection/php_reflection.c (working copy)
@@ -356,8 +356,8 @@
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 @@
string_printf(str, "%s%s [ ", indent, kind);
}
string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" :
"<internal");
- if (ce->module) {
- string_printf(str, ":%s", ce->module->name);
+ if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
+ string_printf(str, ":%s", ce->info.internal.module->name);
}
string_printf(str, "> ");
if (ce->get_iterator != NULL) {
@@ -414,8 +414,8 @@
/* 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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
struct _zend_module_entry *module = va_arg(args, struct
_zend_module_entry*);
int add_reflection_class = va_arg(args, int);
- if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
+ if (((*pce)->type == ZEND_INTERNAL_CLASS) &&
(*pce)->info.internal.module && !strcasecmp((*pce)->info.internal.module->name,
module->name)) {
if (add_reflection_class) {
ALLOC_ZVAL(zclass);
zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
Index: Zend/zend.h
===================================================================
--- Zend/zend.h (revision 303306)
+++ Zend/zend.h (working copy)
@@ -465,7 +465,6 @@
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 @@
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 @@
zend_trait_alias **trait_aliases;
zend_trait_precedence **trait_precedences;
- char *filename;
- zend_uint line_start;
- zend_uint line_end;
- char *doc_comment;
- zend_uint doc_comment_len;
-
- struct _zend_module_entry *module;
+ union {
+ struct {
+ char *filename;
+ zend_uint line_start;
+ zend_uint line_end;
+ char *doc_comment;
+ zend_uint doc_comment_len;
+ } user;
+ struct {
+ const struct _zend_function_entry *builtin_functions;
+ struct _zend_module_entry *module;
+ } internal;
+ } info;
};
#include "zend_stream.h"
Index: Zend/zend_execute.c
===================================================================
--- Zend/zend_execute.c (revision 303306)
+++ Zend/zend_execute.c (working copy)
@@ -1476,7 +1476,7 @@
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int
return_value_used TSRMLS_DC)
{
zval **return_value_ptr = &(*(temp_variable *)((char *)
execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr;
- ((zend_internal_function *)
execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value,
*return_value_ptr,
execute_data_ptr->function_state.function->common.return_reference?return_value_ptr:NULL,
execute_data_ptr->object, return_value_used TSRMLS_CC);
+ ((zend_internal_function *)
execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value,
*return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags
& ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object,
return_value_used TSRMLS_CC);
}
#define ZEND_VM_NEXT_OPCODE() \
Index: Zend/zend_closures.c
===================================================================
--- Zend/zend_closures.c (revision 303306)
+++ Zend/zend_closures.c (working copy)
@@ -129,7 +129,7 @@
invoke->common = closure->func.common;
invoke->type = ZEND_INTERNAL_FUNCTION;
- invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC |
ZEND_ACC_CALL_VIA_HANDLER;
+ invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC |
ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags &
ZEND_ACC_RETURN_REFERENCE);
invoke->internal_function.handler = ZEND_MN(Closure___invoke);
invoke->internal_function.module = 0;
invoke->internal_function.scope = zend_ce_closure;
Index: Zend/zend_object_handlers.c
===================================================================
--- Zend/zend_object_handlers.c (revision 303306)
+++ Zend/zend_object_handlers.c (working copy)
@@ -938,15 +938,13 @@
{
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 @@
{
zend_internal_function *callstatic_user_call =
emalloc(sizeof(zend_internal_function));
callstatic_user_call->type = ZEND_INTERNAL_FUNCTION;
- callstatic_user_call->module = ce->module;
+ callstatic_user_call->module = (ce->type == ZEND_INTERNAL_CLASS) ?
ce->info.internal.module : NULL;
callstatic_user_call->handler = zend_std_callstatic_user_call;
callstatic_user_call->arg_info = NULL;
callstatic_user_call->num_args = 0;
callstatic_user_call->scope = ce;
callstatic_user_call->fn_flags = ZEND_ACC_STATIC | ZEND_ACC_PUBLIC |
ZEND_ACC_CALL_VIA_HANDLER;
callstatic_user_call->function_name = estrndup(method_name, method_len);
- callstatic_user_call->pass_rest_by_reference = 0;
- callstatic_user_call->return_reference = ZEND_RETURN_VALUE;
return (zend_function *)callstatic_user_call;
}
Index: Zend/zend_compile.c
===================================================================
--- Zend/zend_compile.c (revision 303306)
+++ Zend/zend_compile.c (working copy)
@@ -170,6 +170,16 @@
}
/* }}} */
+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 @@
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 @@
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 @@
}
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;
@@ -343,9 +352,9 @@
{
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;
@@ -1049,8 +1058,8 @@
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 @@
/* 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 @@
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 @@
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;
}
@@ -1683,6 +1696,8 @@
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 @@
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_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 @@
} 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 @@
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_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 @@
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 @@
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 @@
}
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 @@
}
}
- 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 @@
}
}
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 @@
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 @@
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 @@
}
/* 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 @@
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) {
@@ -4572,8 +4581,8 @@
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 @@
}
}
- 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 @@
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 @@
#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 @@
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 @@
efree(c_ns_name);
} else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1,
(void**)&pce) == SUCCESS &&
(*pce)->type == ZEND_USER_CLASS &&
- (*pce)->filename == CG(compiled_filename)) {
+ (*pce)->info.user.filename == CG(compiled_filename)) {
char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns),
Z_STRLEN_P(ns));
if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
Index: Zend/zend_compile.h
===================================================================
--- Zend/zend_compile.h (revision 303306)
+++ Zend/zend_compile.h (working copy)
@@ -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 @@
#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 @@
/* 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 @@
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 @@
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 @@
/* static variables support */
HashTable *static_variables;
- zend_op *start_op;
- int backpatch_count;
-
zend_uint this_var;
char *filename;
@@ -262,7 +284,7 @@
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 @@
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 @@
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 @@
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 @@
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 */
@@ -766,22 +786,21 @@
#define ZEND_SEND_BY_REF 1
#define ZEND_SEND_PREFER_REF 2
-#define ARG_SEND_TYPE(zf, arg_num)
\
- ((zf) ?
\
- ((((zend_function*)(zf))->common.arg_info &&
\
- arg_num<=((zend_function*)(zf))->common.num_args) ?
\
- ((zend_function *)(zf))->common.arg_info[arg_num-1].pass_by_reference
: \
- ((zend_function *)(zf))->common.pass_rest_by_reference) :
\
- ZEND_SEND_BY_VAL)
+#define CHECK_ARG_SEND_TYPE(zf, arg_num, m1, m2)
\
+ ((zf) &&
\
+ ((((zend_function*)(zf))->common.arg_info &&
\
+ arg_num <= ((zend_function*)(zf))->common.num_args) ?
\
+ (((zend_function
*)(zf))->common.arg_info[arg_num-1].pass_by_reference & (m1)) : \
+ (((zend_function *)(zf))->common.fn_flags & (m2))))
#define ARG_MUST_BE_SENT_BY_REF(zf, arg_num) \
- (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_BY_REF)
+ CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF,
ZEND_ACC_PASS_REST_BY_REFERENCE)
#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
- (ARG_SEND_TYPE(zf, arg_num) & (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF))
+ CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF,
ZEND_ACC_PASS_REST_BY_REFERENCE|ZEND_ACC_PASS_REST_PREFER_REF)
#define ARG_MAY_BE_SENT_BY_REF(zf, arg_num) \
- (ARG_SEND_TYPE(zf, arg_num) == ZEND_SEND_PREFER_REF)
+ CHECK_ARG_SEND_TYPE(zf, arg_num, ZEND_SEND_PREFER_REF,
ZEND_ACC_PASS_REST_PREFER_REF)
#define ZEND_RETURN_VAL 0
#define ZEND_RETURN_REF 1
Index: Zend/zend_vm_def.h
===================================================================
--- Zend/zend_vm_def.h (revision 303306)
+++ Zend/zend_vm_def.h (working copy)
@@ -2578,7 +2578,7 @@
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 @@
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 @@
ret->var.ptr = NULL;
EG(return_value_ptr_ptr) = &ret->var.ptr;
ret->var.ptr_ptr = &ret->var.ptr;
- ret->var.fcall_returned_reference =
fbc->common.return_reference;
+ ret->var.fcall_returned_reference =
(fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
}
if (EXPECTED(zend_execute == execute)) {
Index: Zend/zend_vm_execute.skl
===================================================================
--- Zend/zend_vm_execute.skl (revision 303306)
+++ Zend/zend_vm_execute.skl (working copy)
@@ -55,7 +55,7 @@
}
}
- EX(opline) = op_array->start_op ? op_array->start_op :
op_array->opcodes;
+ EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) !=
0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
EG(opline_ptr) = &EX(opline);
LOAD_OPLINE();
Index: Zend/zend_language_scanner.l
===================================================================
--- Zend/zend_language_scanner.l (revision 303306)
+++ Zend/zend_language_scanner.l (working copy)
@@ -351,6 +351,7 @@
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 @@
init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE
TSRMLS_CC);
CG(interactive) = orig_interactive;
CG(active_op_array) = op_array;
+ zend_init_compiler_context(TSRMLS_C);
BEGIN(ST_IN_SCRIPTING);
compiler_result = zendparse(TSRMLS_C);
Index: Zend/zend_API.c
===================================================================
--- Zend/zend_API.c (revision 303306)
+++ Zend/zend_API.c (working copy)
@@ -1015,7 +1015,7 @@
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 @@
}
*scope = old_scope;
- class_type->constants_updated = 1;
+ class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
}
}
/* }}} */
@@ -1953,36 +1953,44 @@
internal_function->function_name = (char*)ptr->fname;
internal_function->scope = scope;
internal_function->prototype = NULL;
+ if (ptr->flags) {
+ if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
+ if (ptr->flags != ZEND_ACC_DEPRECATED || scope)
{
+ zend_error(error_type, "Invalid access
level for %s%s%s() - access must be exactly one of public, protected or
private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
+ }
+ internal_function->fn_flags = ZEND_ACC_PUBLIC |
ptr->flags;
+ } else {
+ internal_function->fn_flags = ptr->flags;
+ }
+ } 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 (ptr->arg_info[0].required_num_args == -1) {
+ if (info->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->required_num_args =
info->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;
+ 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;
- 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)
{
- zend_error(error_type, "Invalid access
level for %s%s%s() - access must be exactly one of public, protected or
private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
- }
- internal_function->fn_flags = ZEND_ACC_PUBLIC |
ptr->flags;
- } else {
- internal_function->fn_flags = ptr->flags;
- }
- } else {
- internal_function->fn_flags = ZEND_ACC_PUBLIC;
- }
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 @@
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 @@
if (strict_class && ce_org->__call) {
fcc->function_handler =
emalloc(sizeof(zend_internal_function));
fcc->function_handler->internal_function.type =
ZEND_INTERNAL_FUNCTION;
- fcc->function_handler->internal_function.module
= ce_org->module;
+ fcc->function_handler->internal_function.module
= (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL;
fcc->function_handler->internal_function.handler = zend_std_call_user_call;
fcc->function_handler->internal_function.arg_info = NULL;
fcc->function_handler->internal_function.num_args = 0;
fcc->function_handler->internal_function.scope
= ce_org;
fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
-
fcc->function_handler->internal_function.pass_rest_by_reference = 0;
-
fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
call_via_handler = 1;
retval = 1;
} else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
Index: Zend/zend_API.h
===================================================================
--- Zend/zend_API.h (revision 303306)
+++ Zend/zend_API.h (working copy)
@@ -96,14 +96,14 @@
#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 @@
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 @@
class_container.interfaces = NULL;
\
class_container.get_iterator = NULL;
\
class_container.iterator_funcs.funcs = NULL;
\
- class_container.module = NULL;
\
+ class_container.info.internal.module = NULL;
\
+ class_container.info.internal.builtin_functions = functions;
\
}
#define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions,
handle_fcall, handle_propget, handle_propset) \
Index: Zend/zend_globals.h
===================================================================
--- Zend/zend_globals.h (revision 303306)
+++ Zend/zend_globals.h (working copy)
@@ -139,8 +139,8 @@
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 @@
zend_bool active;
+ zend_op *start_op;
+
void *saved_fpu_cw_ptr;
#if XPFPA_HAVE_CW
XPFPA_CW_DATATYPE saved_fpu_cw;
Index: Zend/zend_execute_API.c
===================================================================
--- Zend/zend_execute_API.c (revision 303306)
+++ Zend/zend_execute_API.c (working copy)
@@ -194,6 +194,7 @@
EG(active_op_array) = NULL;
EG(active) = 1;
+ EG(start_op) = NULL;
}
/* }}} */
@@ -1256,7 +1257,7 @@
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;
@@ -1268,11 +1269,11 @@
ret_opline->op1.constant = zend_add_literal(CG(active_op_array),
&EG(uninitialized_zval));
SET_UNUSED(ret_opline->op2);
- if (!CG(active_op_array)->start_op) {
- CG(active_op_array)->start_op = CG(active_op_array)->opcodes;
+ if (!EG(start_op)) {
+ EG(start_op) = CG(active_op_array)->opcodes;
}
- opline=CG(active_op_array)->start_op;
+ opline=EG(start_op);
end=CG(active_op_array)->opcodes+CG(active_op_array)->last;
while (opline<end) {
@@ -1317,7 +1318,7 @@
}
CG(active_op_array)->last -= 1; /* get rid of that ZEND_RETURN */
- CG(active_op_array)->start_op =
CG(active_op_array)->opcodes+CG(active_op_array)->last;
+ EG(start_op) = CG(active_op_array)->opcodes+CG(active_op_array)->last;
}
/* }}} */
Index: Zend/zend_opcode.c
===================================================================
--- Zend/zend_opcode.c (revision 303306)
+++ Zend/zend_opcode.c (working copy)
@@ -43,31 +43,28 @@
}
}
-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 @@
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 @@
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 @@
if (ce->num_interfaces > 0) {
free(ce->interfaces);
}
- if (ce->doc_comment) {
- free(ce->doc_comment);
- }
free(ce);
break;
}
@@ -410,7 +397,7 @@
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_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_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 @@
opline++;
}
- op_array->done_pass_two = 1;
+ op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return 0;
}
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php