Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » PHP
  • » [PHP-DEV] Delayed early binding patch [RSS Feed]

#1 March 13, 2008 09:57:32

Dmitry S.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] Delayed early binding patch


Hi,

I have separated fixes and optimizations from the delayed early binding itself
and added comments about options. Now the patch must be more clear.

The order of actual class declaration in PHP scripts doesn't follow to syntax
order. Some classes might be declared at compile-time (early binding - the
classes which don't implement interfaces and doesn't have parent or have parent
class that is known during compilation) others only in run-time. Many
applications depend on this order and will be broken in case if we disable
early binding. On the other hand early binding provides a big problem for
opcode caches which are not able to emulate it properly. The early binding
itself is impossible because caches cannot create cross-script dependencies or
dependencies from internal classes. So most of them try to emulate early
binding during restoring script from cache, but in fact they may declare
classes that were never declared at compile time (for example class
declarations wrapped by тАЬifтАЭ statementтАЭ).

The path for PHP_5_3 is going to provide a general solution to control some
aspect of PHP compilation. The patch introduces CG(compiler_options) that is a
bit-set of compiler flags. ZE provides two default sets of the options. One for
script compilation and another for code evaluation. Some extensions like opcode
caches and debuggers might set (or reset) individual flags in the
CG(compiler_options).

The patch defines the following options:

ZEND_COMPILE_EXTENDED_INFO is a replacement of CG(extended_info)

ZEND_COMPILE_HANDLE_OP_ARRAY is a replacement CG(handle_op_arrays)

ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS disables generation of direct calls to
internal functions (ZEND_DO_FCALL) and use indirect calls
(ZEND_INIT_FCALL_BY_NAME + ZEND_DO_FCALL_BY_NAME). This flag may be useful if
script compiled by one PHP binary but executed by another, which may miss some
internal functions.

ZEND_COMPILE_IGNORE_INTERNAL_CLASSES disables usage of internal classes during
compilation. It disables early binding of classes with parent internal classes.
Also all non-compound names in namespaces might be resolved to internal classes
at runtime.

ZEND_COMPILE_DELAYED_BINDING changes ZEND_DECLARE_INHERITED_CLASS opcode into
ZEND_DECLARE_INHERITED_CLASS_DELAYD for all opcodes that were failed to perform
early binding because of inexistence of parent class. This flag is especial
useful with caches which have to perform early binding during
script-loading-time instead of compile-time. In case if parent class doesn't
exists at script-loading-time too, actual class declaration will be finally
delayed to run-time.

So to use delayed early binding, opcode cache should set proper flags and then
call the original compiler.

cache_compile_file() {
...
orig_compiler_options = CG(compiler_options);
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES |
ZEND_COMPILE_DELAYED_BINDING;
ret = orig_compile_file();
CG(compiler_options) = orig_compiler_options;
...
retur ret;
}

And then call to zend_do_delayed_early_binding() for op_array of each restored
script.

Thanks. Dmitry.Index: Zend/zend.c
===================================================================
RCS file: /repository/ZendEngine2/zend.c,v
retrieving revision 1.308.2.12.2.35.2.10
diff -u -p -d -r1.308.2.12.2.35.2.10 zend.c
--- Zend/zend.c 8 Mar 2008 21:54:03 -0000 1.308.2.12.2.35.2.10
+++ Zend/zend.c 12 Mar 2008 11:06:36 -0000
@@ -446,15 +446,15 @@ static void register_standard_class(TSRM
/* }}} */

#ifdef ZTS
-static zend_bool asp_tags_default = 0;
-static zend_bool short_tags_default = 1;
-static zend_bool ct_pass_ref_default = 1;
-static zend_bool extended_info_default = 0;
+static zend_bool asp_tags_default = 0;
+static zend_bool short_tags_default = 1;
+static zend_bool ct_pass_ref_default = 1;
+static zend_uint compiler_options_default = ZEND_COMPILE_DEFAULT;
#else
-# define asp_tags_default 0
-# define short_tags_default 1
-# define ct_pass_ref_default 1
-# define extended_info_default 0
+# define asp_tags_default 0
+# define short_tags_default 1
+# define ct_pass_ref_default 1
+# define compiler_options_default ZEND_COMPILE_DEFAULT
#endif

static void zend_set_default_compile_time_values(TSRMLS_D) /* {{{ */
@@ -463,7 +463,7 @@ static void zend_set_default_compile_tim
CG(asp_tags) = asp_tags_default;
CG(short_tags) = short_tags_default;
CG(allow_call_time_pass_reference) = ct_pass_ref_default;
- CG(extended_info) = extended_info_default;
+ CG(compiler_options) = compiler_options_default;
}
/* }}} */

@@ -728,7 +728,7 @@ void zend_post_startup(TSRMLS_D) /* {{{
asp_tags_default = CG(asp_tags);
short_tags_default = CG(short_tags);
ct_pass_ref_default = CG(allow_call_time_pass_reference);
- extended_info_default = CG(extended_info);
+ compiler_options_default = CG(compiler_options);

zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
free(compiler_globals->function_table);
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.49
diff -u -p -d -r1.647.2.27.2.41.2.49 zend_compile.c
--- Zend/zend_compile.c 12 Mar 2008 10:40:02 -0000 1.647.2.27.2.41.2.49
+++ Zend/zend_compile.c 12 Mar 2008 11:06:37 -0000
@@ -137,7 +137,6 @@ void zend_init_compiler_data_structures(
zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
zend_stack_init(&CG(list_stack));
- CG(handle_op_arrays) = 1;
CG(in_compilation) = 0;
CG(start_lineno) = 0;
CG(current_namespace) = NULL;
@@ -1259,7 +1258,7 @@ void zend_do_begin_function_declaration(
zend_hash_update(CG(function_table),
opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len,
&op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
}

- if (CG(extended_info)) {
+ if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

opline->opcode = ZEND_EXT_NOP;
@@ -1438,7 +1437,9 @@ int zend_do_begin_function_call(znode *f
}

lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val,
function_name->u.constant.value.str.len);
- if (zend_hash_find(CG(function_table), lcname,
function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
+ if ((zend_hash_find(CG(function_table), lcname,
function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) ||
+ ((CG(compiler_options) &
ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
+ (function->type == ZEND_INTERNAL_FUNCTION))) {
zend_do_begin_dynamic_function_call(function_name, prefix_len
TSRMLS_CC);
efree(lcname);
return 1; /* Dynamic */
@@ -1621,8 +1622,9 @@ void zend_resolve_class_name(znode *clas
efree(ns_lcname);
}

- if (zend_hash_find(CG(class_table), lcname,
Z_STRLEN(class_name->u.constant)+1, (void**)&pce) == SUCCESS &&
- (*pce)->type == ZEND_INTERNAL_CLASS) {
+ if ((CG(compiler_options) &
ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) ||
+ (zend_hash_find(CG(class_table), lcname,
Z_STRLEN(class_name->u.constant)+1, (void**)&pce) == SUCCESS &&
+ (*pce)->type == ZEND_INTERNAL_CLASS)) {
/* There is an internal class with the same name
exists.
PHP will need to perform additional cheks at
run-time to
determine if we assume class in current
namespace or
@@ -2744,7 +2746,6 @@ void zend_do_early_binding(TSRMLS_D)
{
zend_op *opline =
&CG(active_op_array)->opcodes;
HashTable *table;
- zend_bool is_abstract_class = 0;

while (opline->opcode == ZEND_TICKS && opline >
CG(active_op_array)->opcodes) {
opline--;
@@ -2758,57 +2759,49 @@ void zend_do_early_binding(TSRMLS_D)
table = CG(function_table);
break;
case ZEND_DECLARE_CLASS:
+ if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC)
== NULL) {
+ return;
+ }
+ table = CG(class_table);
+ break;
case ZEND_DECLARE_INHERITED_CLASS:
- is_abstract_class = 1;
- /* break missing intentionally */
- case ZEND_VERIFY_ABSTRACT_CLASS: {
- zend_op *verify_abstract_class_op = opline;
-
- if (!is_abstract_class) {
- opline--;
- }
- if (opline->opcode == ZEND_DECLARE_CLASS) {
- if (do_bind_class(opline,
CG(class_table), 1 TSRMLS_CC) == NULL) {
- return;
- }
- } else if (opline->opcode ==
ZEND_DECLARE_INHERITED_CLASS) {
- zval *parent_name =
&(opline-1)->op2.u.constant;
- zend_class_entry **pce;
+ {
+ zend_op *fetch_class_opline = opline-1;
+ zval *parent_name =
&fetch_class_opline->op2.u.constant;
+ zend_class_entry **pce;

- if
(zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce
TSRMLS_CC) == FAILURE) {
- return;
- }
- if (do_bind_inherited_class(opline,
CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
- return;
- }
- /* clear unnecessary ZEND_FETCH_CLASS
opcode */
- if (opline >
CG(active_op_array)->opcodes &&
- (opline-1)->opcode ==
ZEND_FETCH_CLASS) {
- zend_op *fetch_class_opline =
opline-1;
+ if ((zend_lookup_class(Z_STRVAL_P(parent_name),
Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
+ ((CG(compiler_options) &
ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
+ ((*pce)->type == ZEND_INTERNAL_CLASS))) {
+ if (CG(compiler_options) &
ZEND_COMPILE_DELAYED_BINDING) {
+ zend_uint *opline_num =
&CG(active_op_array)->early_binding;

-
zval_dtor(&fetch_class_opline->op2.u.constant);
- fetch_class_opline->opcode =
ZEND_NOP;
-
memset(&fetch_class_opline->op1, 0, sizeof(znode));
-
memset(&fetch_class_opline->op2, 0, sizeof(znode));
-
SET_UNUSED(fetch_class_opline->op1);
-
SET_UNUSED(fetch_class_opline->op2);
-
SET_UNUSED(fetch_class_opline->result);
+ while (*opline_num != -1) {
+ opline_num =
&CG(active_op_array)->opcodes.result.u.opline_num;
+ }
+ *opline_num = opline -
CG(active_op_array)->opcodes;
+ opline->opcode =
ZEND_DECLARE_INHERITED_CLASS_DELAYED;
+ opline->result.op_type =
IS_UNUSED;
+ opline->result.u.opline_num =
-1;
}
- } else {
- /* We currently don't early-bind
classes that implement interfaces */
return;
}
- table = CG(class_table);
- if (!is_abstract_class) {
- /* clear the verify_abstract_class op */
- init_op(verify_abstract_class_op
TSRMLS_CC);
-
SET_UNUSED(verify_abstract_class_op->op1);
-
SET_UNUSED(verify_abstract_class_op->op2);
- verify_abstract_class_op->opcode =
ZEND_NOP;
+ if (do_bind_inherited_class(opline,
CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
+ return;
}
- }
+ /* clear unnecessary ZEND_FETCH_CLASS opcode */
+ zval_dtor(&fetch_class_opline->op2.u.constant);
+ fetch_class_opline->opcode = ZEND_NOP;
+ memset(&fetch_class_opline->op1, 0,
sizeof(znode));
+ memset(&fetch_class_opline->op2, 0,
sizeof(znode));
+ SET_UNUSED(fetch_class_opline->op1);
+ SET_UNUSED(fetch_class_opline->op2);
+ SET_UNUSED(fetch_class_opline->result);

- break;
+ table = CG(class_table);
+ break;
+ }
+ case ZEND_VERIFY_ABSTRACT_CLASS:
case ZEND_ADD_INTERFACE:
/* We currently don't early-bind classes that implement
interfaces */
return;
@@ -2827,6 +2820,23 @@ void zend_do_early_binding(TSRMLS_D)
SET_UNUSED(opline->op2);
}

+ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array TSRMLS_DC)
+{
+ if (op_array->early_binding != -1) {
+ zend_bool orig_in_compilation = CG(in_compilation);
+ zend_uint opline_num = op_array->early_binding;
+ zend_class_entry **pce;
+
+ CG(in_compilation) = 1;
+ while (opline_num != -1) {
+ if
(zend_lookup_class(Z_STRVAL(op_array->opcodes.op2.u.constant),
Z_STRLEN(op_array->opcodes.op2.u.constant), &pce TSRMLS_CC) ==
SUCCESS) {
+
do_bind_inherited_class(&op_array->opcodes, EG(class_table), *pce,
1 TSRMLS_CC);
+ }
+ opline_num =
op_array->opcodes.result.u.opline_num;
+ }
+ CG(in_compilation) = orig_in_compilation;
+ }
+}

void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC)
{
@@ -4500,7 +4510,7 @@ void zend_do_extended_info(TSRMLS_D)
{
zend_op *opline;

- if (!CG(extended_info)) {
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
return;
}

@@ -4516,7 +4526,7 @@ void zend_do_extended_fcall_begin(TSRMLS
{
zend_op *opline;

- if (!CG(extended_info)) {
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
return;
}

@@ -4532,7 +4542,7 @@ void zend_do_extended_fcall_end(TSRMLS_D
{
zend_op *opline;

- if (!CG(extended_info)) {
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
return;
}

Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.12.2.15
diff -u -p -d -r1.316.2.8.2.12.2.15 zend_compile.h
--- Zend/zend_compile.h 12 Mar 2008 09:46:42 -0000 1.316.2.8.2.12.2.15
+++ Zend/zend_compile.h 12 Mar 2008 11:06:37 -0000
@@ -224,6 +224,7 @@ struct _zend_op_array {
zend_uint line_end;
char *doc_comment;
zend_uint doc_comment_len;
+ zend_uint early_binding; /* the linked list of delayed declarations */

void *reserved;
};
@@ -428,6 +429,7 @@ void zend_do_implements_interface(znode

ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry
*parent_ce TSRMLS_DC);
void zend_do_early_binding(TSRMLS_D);
+ZEND_API void zend_do_delayed_early_binding(zend_op_array *op_array TSRMLS_DC);

void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC);

@@ -720,6 +722,32 @@ END_EXTERN_C()
#define ZEND_TOSTRING_FUNC_NAME "__tostring"
#define ZEND_AUTOLOAD_FUNC_NAME "__autoload"

+/* The following constants may be combined in CG(compiler_options)
+ * to change the default compiler behavior */
+
+/* generate extended debug information */
+#define ZEND_COMPILE_EXTENDED_INFO (1<<0)
+
+/* call op_array handler of extendions */
+#define ZEND_COMPILE_HANDLE_OP_ARRAY (1<<1)
+
+/* generate ZEND_DO_FCALL_BY_NAME for internal functions instead of
ZEND_DO_FCALL */
+#define ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS (1<<2)
+
+/* don't perform early binding for classes inherited form internal ones;
+ * in namespaces assume that internal class that doesn't exist at compile-time
+ * may apper in run-time */
+#define ZEND_COMPILE_IGNORE_INTERNAL_CLASSES (1<<3)
+
+/* generate ZEND_DECLARE_INHERITED_CLASS_DELAYED opcode to delay early binding
*/
+#define ZEND_COMPILE_DELAYED_BINDING (1<<4)
+
+/* The default value for CG(compiler_options) */
+#define ZEND_COMPILE_DEFAULT
ZEND_COMPILE_HANDLE_OP_ARRAY
+
+/* The default value for CG(compiler_options) during eval() */
+#define ZEND_COMPILE_DEFAULT_FOR_EVAL 0
+
#endif /* ZEND_COMPILE_H */

/*
Index: Zend/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.20.2.24.2.28
diff -u -p -d -r1.331.2.20.2.24.2.28 zend_execute_API.c
--- Zend/zend_execute_API.c 9 Mar 2008 20:52:29 -0000
1.331.2.20.2.24.2.28
+++ Zend/zend_execute_API.c 12 Mar 2008 11:06:37 -0000
@@ -1264,7 +1264,7 @@ ZEND_API int zend_eval_string(char *str,
zval pv;
zend_op_array *new_op_array;
zend_op_array *original_active_op_array = EG(active_op_array);
- zend_uchar original_handle_op_arrays;
+ zend_uint original_compiler_options;
int retval;

if (retval_ptr) {
@@ -1284,10 +1284,10 @@ ZEND_API int zend_eval_string(char *str,

/*printf("Evaluating '%s'\n", pv.value.str.val);*/

- original_handle_op_arrays = CG(handle_op_arrays);
- CG(handle_op_arrays) = 0;
+ original_compiler_options = CG(compiler_options);
+ CG(handle_op_arrays) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
new_op_array = zend_compile_string(&pv, string_name TSRMLS_CC);
- CG(handle_op_arrays) = original_handle_op_arrays;
+ CG(compiler_options) = original_compiler_options;

if (new_op_array) {
zval *local_retval_ptr=NULL;
Index: Zend/zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.141.2.3.2.7.2.8
diff -u -p -d -r1.141.2.3.2.7.2.8 zend_globals.h
--- Zend/zend_globals.h 8 Mar 2008 21:54:03 -0000 1.141.2.3.2.7.2.8
+++ Zend/zend_globals.h 12 Mar 2008 11:06:37 -0000
@@ -59,6 +59,9 @@ END_EXTERN_C()
/* excpt.h on Digital Unix 4.0 defines function_table */
#undef function_table

+#define ZEND_EARLY_BINDING_COMPILE_TIME 0
+#define ZEND_EARLY_BINDING_DELAYED 1
+#define ZEND_EARLY_BINDING_DELAYED_ALL 2

typedef struct _zend_declarables {
zval ticks;
@@ -106,7 +109,6 @@ struct _zend_compiler_globals {
zend_declarables declarables;

/* For extensions support */
- zend_bool extended_info; /* generate extension information for
debugger/profiler */
zend_bool handle_op_arrays; /* run op_arrays through op_array
handlers */

zend_bool unclean_shutdown;
@@ -131,6 +133,8 @@ struct _zend_compiler_globals {
char *doc_comment;
zend_uint doc_comment_len;

+ zend_uint compiler_options; /* set of ZEND_COMPILE_* constants */
+
zval *current_namespace;
HashTable *current_import;

Index: Zend/zend_opcode.c
===================================================================
RCS file: /repository/ZendEngine2/zend_opcode.c,v
retrieving revision 1.110.2.6.2.3.2.5
diff -u -p -d -r1.110.2.6.2.3.2.5 zend_opcode.c
--- Zend/zend_opcode.c 31 Dec 2007 07:17:04 -0000 1.110.2.6.2.3.2.5
+++ Zend/zend_opcode.c 12 Mar 2008 11:06:37 -0000
@@ -101,6 +101,8 @@ void init_op_array(zend_op_array *op_arr

op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0;

+ op_array->early_binding = -1;
+
memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES *
sizeof(void*));

zend_llist_apply_with_argument(&zend_extensions,
(llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array
TSRMLS_CC);
@@ -364,10 +366,10 @@ int pass_two(zend_op_array *op_array TSR
if (op_array->type!=ZEND_USER_FUNCTION &&
op_array->type!=ZEND_EVAL_CODE) {
return 0;
}
- if (CG(extended_info)) {
+ if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
zend_update_extended_info(op_array TSRMLS_CC);
}
- if (CG(handle_op_arrays)) {
+ if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) {
zend_llist_apply_with_argument(&zend_extensions,
(llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array
TSRMLS_CC);
}

Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.42
diff -u -p -d -r1.59.2.29.2.48.2.42 zend_vm_def.h
--- Zend/zend_vm_def.h 12 Mar 2008 10:32:11 -0000 1.59.2.29.2.48.2.42
+++ Zend/zend_vm_def.h 12 Mar 2008 11:06:37 -0000
@@ -3962,6 +3962,19 @@ ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERI
ZEND_VM_NEXT_OPCODE();
}

+ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
+{
+ zend_op *opline = EX(opline);
+ zend_class_entry **pce, **pce_orig;
+
+ if (zend_hash_find(EG(class_table), Z_STRVAL(opline->op2.u.constant),
Z_STRLEN(opline->op2.u.constant)+1, (void**)&pce) == FAILURE ||
+ (zend_hash_find(EG(class_table), Z_STRVAL(opline->op1.u.constant),
Z_STRLEN(opline->op1.u.constant), (void**)&pce_orig) == SUCCESS &&
+ *pce != *pce_orig)) {
+ do_bind_inherited_class(opline, EG(class_table),
EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ }
+ ZEND_VM_NEXT_OPCODE();
+}
+
ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
{
do_bind_function(EX(opline), EG(function_table), 0);
Index: Zend/zend_vm_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.62.2.30.2.49.2.41
diff -u -p -d -r1.62.2.30.2.49.2.41 zend_vm_execute.h
--- Zend/zend_vm_execute.h 12 Mar 2008 10:32:12 -0000
1.62.2.30.2.49.2.41
+++ Zend/zend_vm_execute.h 12 Mar 2008 11:06:39 -0000
@@ -482,6 +482,19 @@ static int ZEND_DECLARE_INHERITED_CLASS_
ZEND_VM_NEXT_OPCODE();
}

+static int
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+ zend_class_entry **pce, **pce_orig;
+
+ if (zend_hash_find(EG(class_table), Z_STRVAL(opline->op2.u.constant),
Z_STRLEN(opline->op2.u.constant)+1, (void**)&pce) == FAILURE ||
+ (zend_hash_find(EG(class_table), Z_STRVAL(opline->op1.u.constant),
Z_STRLEN(opline->op1.u.constant), (void**)&pce_orig) == SUCCESS &&
+ *pce != *pce_orig)) {
+ do_bind_inherited_class(opline, EG(class_table),
EX_T(opline->extended_value).class_entry, 0 TSRMLS_CC);
+ }
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
do_bind_function(EX(opline), EG(function_table), 0);
@@ -32990,31 +33003,31 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
+ ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
Index: Zend/zend_vm_opcodes.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_opcodes.h,v
retrieving revision 1.42.2.17.2.1.2.4
diff -u -p -d -r1.42.2.17.2.1.2.4 zend_vm_opcodes.h
--- Zend/zend_vm_opcodes.h 31 Dec 2007 07:17:06 -0000
1.42.2.17.2.1.2.4
+++ Zend/zend_vm_opcodes.h 12 Mar 2008 11:06:39 -0000
@@ -18,135 +18,136 @@
+----------------------------------------------------------------------+
*/

-#define ZEND_NOP 0
-#define ZEND_ADD 1
-#define ZEND_SUB 2
-#define ZEND_MUL 3
-#define ZEND_DIV 4
-#define ZEND_MOD 5
-#define ZEND_SL 6
-#define ZEND_SR 7
-#define ZEND_CONCAT 8
-#define ZEND_BW_OR 9
-#define ZEND_BW_AND 10
-#define ZEND_BW_XOR 11
-#define ZEND_BW_NOT 12
-#define ZEND_BOOL_NOT 13
-#define ZEND_BOOL_XOR 14
-#define ZEND_IS_IDENTICAL 15
-#define ZEND_IS_NOT_IDENTICAL 16
-#define ZEND_IS_EQUAL 17
-#define ZEND_IS_NOT_EQUAL 18
-#define ZEND_IS_SMALLER 19
-#define ZEND_IS_SMALLER_OR_EQUAL 20
-#define ZEND_CAST 21
-#define ZEND_QM_ASSIGN 22
-#define ZEND_ASSIGN_ADD 23
-#define ZEND_ASSIGN_SUB 24
-#define ZEND_ASSIGN_MUL 25
-#define ZEND_ASSIGN_DIV 26
-#define ZEND_ASSIGN_MOD 27
-#define ZEND_ASSIGN_SL 28
-#define ZEND_ASSIGN_SR 29
-#define ZEND_ASSIGN_CONCAT 30
-#define ZEND_ASSIGN_BW_OR 31
-#define ZEND_ASSIGN_BW_AND 32
-#define ZEND_ASSIGN_BW_XOR 33
-#define ZEND_PRE_INC 34
-#define ZEND_PRE_DEC 35
-#define ZEND_POST_INC 36
-#define ZEND_POST_DEC 37
-#define ZEND_ASSIGN 38
-#define ZEND_ASSIGN_REF 39
-#define ZEND_ECHO 40
-#define ZEND_PRINT 41
-#define ZEND_JMP 42
-#define ZEND_JMPZ 43
-#define ZEND_JMPNZ 44
-#define ZEND_JMPZNZ 45
-#define ZEND_JMPZ_EX 46
-#define ZEND_JMPNZ_EX 47
-#define ZEND_CASE 48
-#define ZEND_SWITCH_FREE 49
-#define ZEND_BRK 50
-#define ZEND_CONT 51
-#define ZEND_BOOL 52
-#define ZEND_INIT_STRING 53
-#define ZEND_ADD_CHAR 54
-#define ZEND_ADD_STRING 55
-#define ZEND_ADD_VAR 56
-#define ZEND_BEGIN_SILENCE 57
-#define ZEND_END_SILENCE 58
-#define ZEND_INIT_FCALL_BY_NAME 59
-#define ZEND_DO_FCALL 60
-#define ZEND_DO_FCALL_BY_NAME 61
-#define ZEND_RETURN 62
-#define ZEND_RECV 63
-#define ZEND_RECV_INIT 64
-#define ZEND_SEND_VAL 65
-#define ZEND_SEND_VAR 66
-#define ZEND_SEND_REF 67
-#define ZEND_NEW 68
-#define ZEND_INIT_NS_FCALL_BY_NAME 69
-#define ZEND_FREE 70
-#define ZEND_INIT_ARRAY 71
-#define ZEND_ADD_ARRAY_ELEMENT 72
-#define ZEND_INCLUDE_OR_EVAL 73
-#define ZEND_UNSET_VAR 74
-#define ZEND_UNSET_DIM 75
-#define ZEND_UNSET_OBJ 76
-#define ZEND_FE_RESET 77
-#define ZEND_FE_FETCH 78
-#define ZEND_EXIT 79
-#define ZEND_FETCH_R 80
-#define ZEND_FETCH_DIM_R 81
-#define ZEND_FETCH_OBJ_R 82
-#define ZEND_FETCH_W 83
-#define ZEND_FETCH_DIM_W 84
-#define ZEND_FETCH_OBJ_W 85
-#define ZEND_FETCH_RW 86
-#define ZEND_FETCH_DIM_RW 87
-#define ZEND_FETCH_OBJ_RW 88
-#define ZEND_FETCH_IS 89
-#define ZEND_FETCH_DIM_IS 90
-#define ZEND_FETCH_OBJ_IS 91
-#define ZEND_FETCH_FUNC_ARG 92
-#define ZEND_FETCH_DIM_FUNC_ARG 93
-#define ZEND_FETCH_OBJ_FUNC_ARG 94
-#define ZEND_FETCH_UNSET 95
-#define ZEND_FETCH_DIM_UNSET 96
-#define ZEND_FETCH_OBJ_UNSET 97
-#define ZEND_FETCH_DIM_TMP_VAR 98
-#define ZEND_FETCH_CONSTANT 99
-#define ZEND_EXT_STMT 101
-#define ZEND_EXT_FCALL_BEGIN 102
-#define ZEND_EXT_FCALL_END 103
-#define ZEND_EXT_NOP 104
-#define ZEND_TICKS 105
-#define ZEND_SEND_VAR_NO_REF 106
-#define ZEND_CATCH 107
-#define ZEND_THROW 108
-#define ZEND_FETCH_CLASS 109
-#define ZEND_CLONE 110
-#define ZEND_INIT_METHOD_CALL 112
-#define ZEND_INIT_STATIC_METHOD_CALL 113
-#define ZEND_ISSET_ISEMPTY_VAR 114
-#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115
-#define ZEND_PRE_INC_OBJ 132
-#define ZEND_PRE_DEC_OBJ 133
-#define ZEND_POST_INC_OBJ 134
-#define ZEND_POST_DEC_OBJ 135
-#define ZEND_ASSIGN_OBJ 136
-#define ZEND_INSTANCEOF 138
-#define ZEND_DECLARE_CLASS 139
-#define ZEND_DECLARE_INHERITED_CLASS 140
-#define ZEND_DECLARE_FUNCTION 141
-#define ZEND_RAISE_ABSTRACT_ERROR 142
-#define ZEND_DECLARE_CONST 143
-#define ZEND_ADD_INTERFACE 144
-#define ZEND_VERIFY_ABSTRACT_CLASS 146
-#define ZEND_ASSIGN_DIM 147
-#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148
-#define ZEND_HANDLE_EXCEPTION 149
-#define ZEND_USER_OPCODE 150
-#define ZEND_JMP_SET 152
+#define ZEND_NOP 0
+#define ZEND_ADD 1
+#define ZEND_SUB 2
+#define ZEND_MUL 3
+#define ZEND_DIV 4
+#define ZEND_MOD 5
+#define ZEND_SL 6
+#define ZEND_SR 7
+#define ZEND_CONCAT 8
+#define ZEND_BW_OR 9
+#define ZEND_BW_AND 10
+#define ZEND_BW_XOR 11
+#define ZEND_BW_NOT 12
+#define ZEND_BOOL_NOT 13
+#define ZEND_BOOL_XOR 14
+#define ZEND_IS_IDENTICAL 15
+#define ZEND_IS_NOT_IDENTICAL 16
+#define ZEND_IS_EQUAL 17
+#define ZEND_IS_NOT_EQUAL 18
+#define ZEND_IS_SMALLER 19
+#define ZEND_IS_SMALLER_OR_EQUAL 20
+#define ZEND_CAST 21
+#define ZEND_QM_ASSIGN 22
+#define ZEND_ASSIGN_ADD 23
+#define ZEND_ASSIGN_SUB 24
+#define ZEND_ASSIGN_MUL 25
+#define ZEND_ASSIGN_DIV 26
+#define ZEND_ASSIGN_MOD 27
+#define ZEND_ASSIGN_SL 28
+#define ZEND_ASSIGN_SR 29
+#define ZEND_ASSIGN_CONCAT 30
+#define ZEND_ASSIGN_BW_OR 31
+#define ZEND_ASSIGN_BW_AND 32
+#define ZEND_ASSIGN_BW_XOR 33
+#define ZEND_PRE_INC 34
+#define ZEND_PRE_DEC 35
+#define ZEND_POST_INC 36
+#define ZEND_POST_DEC 37
+#define ZEND_ASSIGN 38
+#define ZEND_ASSIGN_REF 39
+#define ZEND_ECHO 40
+#define ZEND_PRINT 41
+#define ZEND_JMP 42
+#define ZEND_JMPZ 43
+#define ZEND_JMPNZ 44
+#define ZEND_JMPZNZ 45
+#define ZEND_JMPZ_EX 46
+#define ZEND_JMPNZ_EX 47
+#define ZEND_CASE 48
+#define ZEND_SWITCH_FREE 49
+#define ZEND_BRK 50
+#define ZEND_CONT 51
+#define ZEND_BOOL 52
+#define ZEND_INIT_STRING 53
+#define ZEND_ADD_CHAR 54
+#define ZEND_ADD_STRING 55
+#define ZEND_ADD_VAR 56
+#define ZEND_BEGIN_SILENCE 57
+#define ZEND_END_SILENCE 58
+#define ZEND_INIT_FCALL_BY_NAME 59
+#define ZEND_DO_FCALL 60
+#define ZEND_DO_FCALL_BY_NAME 61
+#define ZEND_RETURN 62
+#define ZEND_RECV 63
+#define ZEND_RECV_INIT 64
+#define ZEND_SEND_VAL 65
+#define ZEND_SEND_VAR 66
+#define ZEND_SEND_REF 67
+#define ZEND_NEW 68
+#define ZEND_INIT_NS_FCALL_BY_NAME 69
+#define ZEND_FREE 70
+#define ZEND_INIT_ARRAY 71
+#define ZEND_ADD_ARRAY_ELEMENT 72
+#define ZEND_INCLUDE_OR_EVAL 73
+#define ZEND_UNSET_VAR 74
+#define ZEND_UNSET_DIM 75
+#define ZEND_UNSET_OBJ 76
+#define ZEND_FE_RESET 77
+#define ZEND_FE_FETCH 78
+#define ZEND_EXIT 79
+#define ZEND_FETCH_R 80
+#define ZEND_FETCH_DIM_R 81
+#define ZEND_FETCH_OBJ_R 82
+#define ZEND_FETCH_W 83
+#define ZEND_FETCH_DIM_W 84
+#define ZEND_FETCH_OBJ_W 85
+#define ZEND_FETCH_RW 86
+#define ZEND_FETCH_DIM_RW 87
+#define ZEND_FETCH_OBJ_RW 88
+#define ZEND_FETCH_IS 89
+#define ZEND_FETCH_DIM_IS 90
+#define ZEND_FETCH_OBJ_IS 91
+#define ZEND_FETCH_FUNC_ARG 92
+#define ZEND_FETCH_DIM_FUNC_ARG 93
+#define ZEND_FETCH_OBJ_FUNC_ARG 94
+#define ZEND_FETCH_UNSET 95
+#define ZEND_FETCH_DIM_UNSET 96
+#define ZEND_FETCH_OBJ_UNSET 97
+#define ZEND_FETCH_DIM_TMP_VAR 98
+#define ZEND_FETCH_CONSTANT 99
+#define ZEND_EXT_STMT 101
+#define ZEND_EXT_FCALL_BEGIN 102
+#define ZEND_EXT_FCALL_END 103
+#define ZEND_EXT_NOP 104
+#define ZEND_TICKS 105
+#define ZEND_SEND_VAR_NO_REF 106
+#define ZEND_CATCH 107
+#define ZEND_THROW 108
+#define ZEND_FETCH_CLASS 109
+#define ZEND_CLONE 110
+#define ZEND_INIT_METHOD_CALL 112
+#define ZEND_INIT_STATIC_METHOD_CALL 113
+#define ZEND_ISSET_ISEMPTY_VAR 114
+#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115
+#define ZEND_PRE_INC_OBJ 132
+#define ZEND_PRE_DEC_OBJ 133
+#define ZEND_POST_INC_OBJ 134
+#define ZEND_POST_DEC_OBJ 135
+#define ZEND_ASSIGN_OBJ 136
+#define ZEND_INSTANCEOF 138
+#define ZEND_DECLARE_CLASS 139
+#define ZEND_DECLARE_INHERITED_CLASS 140
+#define ZEND_DECLARE_FUNCTION 141
+#define ZEND_RAISE_ABSTRACT_ERROR 142
+#define ZEND_DECLARE_CONST 143
+#define ZEND_ADD_INTERFACE 144
+#define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145
+#define ZEND_VERIFY_ABSTRACT_CLASS 146
+#define ZEND_ASSIGN_DIM 147
+#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148
+#define ZEND_HANDLE_EXCEPTION 149
+#define ZEND_USER_OPCODE 150
+#define ZEND_JMP_SET 152
Index: sapi/cgi/cgi_main.c
===================================================================
RCS file: /repository/php-src/sapi/cgi/cgi_main.c,v
retrieving revision 1.267.2.15.2.50.2.13
diff -u -p -d -r1.267.2.15.2.50.2.13 cgi_main.c
--- sapi/cgi/cgi_main.c 28 Feb 2008 00:51:56 -0000 1.267.2.15.2.50.2.13
+++ sapi/cgi/cgi_main.c 12 Mar 2008 11:06:39 -0000
@@ -1691,7 +1691,7 @@ consult the installation file that came
break;

case 'e': /* enable extended
info output */
- CG(extended_info) = 1;
+ CG(compiler_options) |=
ZEND_COMPILE_EXTENDED_INFO;
break;

case 'f': /* parse file */
Index: sapi/cli/php_cli.c
===================================================================
RCS file: /repository/php-src/sapi/cli/php_cli.c,v
retrieving revision 1.129.2.13.2.22.2.4
diff -u -p -d -r1.129.2.13.2.22.2.4 php_cli.c
--- sapi/cli/php_cli.c 3 Feb 2008 17:49:46 -0000 1.129.2.13.2.22.2.4
+++ sapi/cli/php_cli.c 12 Mar 2008 11:06:40 -0000
@@ -821,7 +821,7 @@ int main(int argc, char *argv)
break;

case 'e': /* enable extended info output */
- CG(extended_info) = 1;
+ CG(compiler_options) |=
ZEND_COMPILE_EXTENDED_INFO;
break;

case 'F':
Index: sapi/milter/php_milter.c
===================================================================
RCS file: /repository/php-src/sapi/milter/php_milter.c,v
retrieving revision 1.14.2.2.2.3.2.2
diff -u -p -d -r1.14.2.2.2.3.2.2 php_milter.c
--- sapi/milter/php_milter.c 31 Dec 2007 07:17:18 -0000 1.14.2.2.2.3.2.2
+++ sapi/milter/php_milter.c 12 Mar 2008 11:06:40 -0000
@@ -1033,7 +1033,7 @@ int main(int argc, char *argv)
break;

case 'e': /* enable extended info output */
- CG(extended_info) = 1;
+ CG(compiler_options) |=
ZEND_COMPILE_EXTENDED_INFO;
break;

case 'f': /* parse file */--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#2 March 13, 2008 11:05:57

Robin F.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] Delayed early binding patch


Hi Dmitry,

On 13/03/2008, Dmitry Stogov <> wrote:
> I have separated fixes and optimizations from the delayed early binding
> itself and added comments about options. Now the patch must be more clear.
>

Thanks, that's really interesting.
As mentioned onhttp://turl.ca/ynny, I'm wondering if there are
already tests in CVS which illustrate the original issue when using
opcode caches. If not, it seems it would be great to add such tests
along with the patch!

Regards,
Robin

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#3 March 13, 2008 13:12:10

Dmitry S.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] Delayed early binding patch


I've attached two tests.
BTW it mighr be hard to run them because opcode caches usually don't
work in CLI mode.

Thanks. Dmitry.

> -----Original Message-----
> From: Robin Fernandes
> Sent: Thursday, March 13, 2008 1:05 PM
> To: Dmitry Stogov
> Cc: internals
> Subject: Re: Delayed early binding patch
>
>
> Hi Dmitry,
>
> On 13/03/2008, Dmitry Stogov <> wrote:
> > I have separated fixes and optimizations from the delayed early
> > binding itself and added comments about options. Now the
> patch must be
> > more clear.
> >
>
> Thanks, that's really interesting.
> As mentioned onhttp://turl.ca/ynny, I'm wondering if there
> are already tests in CVS which illustrate the original issue
> when using opcode caches. If not, it seems it would be great
> to add such tests along with the patch!
>
> Regards,
> Robin
>--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

  • Root
  • » PHP
  • » [PHP-DEV] Delayed early binding patch [RSS Feed]

Board footer

Moderator control

Enjoy the 16th of December
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support