Hi Etienne, We already have patch for late static binding that is very similar to yours. If you have time, please compare them. >From quick look I see that our patch more accurate (it supports constants and runtime function calls) Does our patch miss something that your patch does?
Thanks. Dmitry. > -----Original Message----- > From: Etienne Kneuss [mailto:[EMAIL PROTECTED] > Sent: Friday, August 24, 2007 5:19 PM > To: internals@lists.php.net > Subject: [PHP-DEV] [patch] Late static bindings (LSB) > > > Hi internals, > > here is a patch that implements Late static bindinds in a way that > minimizes the performance hits that were feared. > There is no significant slowdown or memory usage increase > when running > Zend/bench.php, which I assume is a > good enough bench for that kind of matter, as it involves a stupid > amount of (recursive) function calls. > > You can also find the patch here: > http://patches.colder.ch/Zend/late_static_bindings_take6.patch?markup > > Here is a document that describes its usage: > http://colder.ch/news/08-24-2007/28/late-static-bindings-expl.html > > Regards, > > -- > Etienne Kneuss > http://www.colder.ch > > Men never do evil so completely and cheerfully as > when they do it from a religious conviction. > -- Pascal > >
Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.442 diff -u -p -d -r1.442 zend_API.c --- Zend/zend_API.c 20 Aug 2007 09:48:41 -0000 1.442 +++ Zend/zend_API.c 24 Aug 2007 16:50:13 -0000 @@ -2836,6 +2836,9 @@ ZEND_API zend_bool zend_is_callable_ex(z lcname_len == sizeof("parent")-1 && ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "parent", sizeof("parent")-1)) { ce = EG(active_op_array)->scope->parent; + } else if (lcname_len == sizeof("static")-1 && + ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "static", sizeof("static")-1)) { + ce = EG(caller_scope); } else if (zend_u_lookup_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.349 diff -u -p -d -r1.349 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 24 Aug 2007 13:50:52 -0000 1.349 +++ Zend/zend_builtin_functions.c 24 Aug 2007 16:50:13 -0000 @@ -43,6 +43,7 @@ static ZEND_FUNCTION(error_reporting); static ZEND_FUNCTION(define); static ZEND_FUNCTION(defined); static ZEND_FUNCTION(get_class); +static ZEND_FUNCTION(get_caller_class); static ZEND_FUNCTION(get_parent_class); static ZEND_FUNCTION(method_exists); static ZEND_FUNCTION(property_exists); @@ -103,6 +104,7 @@ static zend_function_entry builtin_funct ZEND_FE(define, NULL) ZEND_FE(defined, NULL) ZEND_FE(get_class, NULL) + ZEND_FE(get_caller_class, NULL) ZEND_FE(get_parent_class, NULL) ZEND_FE(method_exists, NULL) ZEND_FE(property_exists, NULL) @@ -614,6 +616,26 @@ ZEND_FUNCTION(get_class) } /* }}} */ +/* {{{ proto string get_caller_class() + Retrieves the class name */ +ZEND_FUNCTION(get_caller_class) +{ + int dup; + + if (!ZEND_NUM_ARGS()) { + if (EG(caller_scope)) { + RETURN_TEXTL(EG(caller_scope)->name, EG(caller_scope)->name_length, 1); + } else { + zend_error(E_ERROR, "get_caller_class() called from outside a class"); + } + } else { + ZEND_WRONG_PARAM_COUNT(); + RETURN_FALSE; + } +} +/* }}} */ + + /* {{{ proto string get_parent_class([mixed object]) U Retrieves the parent class name for object or class or current scope. */ ZEND_FUNCTION(get_parent_class) Index: Zend/zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.765 diff -u -p -d -r1.765 zend_compile.c --- Zend/zend_compile.c 24 Aug 2007 13:50:52 -0000 1.765 +++ Zend/zend_compile.c 24 Aug 2007 16:50:13 -0000 @@ -1702,6 +1702,7 @@ void zend_do_fetch_class(znode *result, switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: case ZEND_FETCH_CLASS_PARENT: + case ZEND_FETCH_CLASS_STATIC: SET_UNUSED(opline->op2); opline->extended_value = fetch_type; zval_dtor(&class_name->u.constant); @@ -3220,6 +3221,9 @@ void zend_do_begin_class_declaration(zno case ZEND_FETCH_CLASS_PARENT: zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved"); break; + case ZEND_FETCH_CLASS_STATIC: + zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved"); + break; default: break; } @@ -3332,6 +3336,9 @@ void zend_do_implements_interface(znode case ZEND_FETCH_CLASS_PARENT: zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as interface name as it is reserved"); break; + case ZEND_FETCH_CLASS_STATIC: + zend_error(E_COMPILE_ERROR, "Cannot use 'static' as interface name as it is reserved"); + break; default: if (CG(active_op_array)->last > 0) { opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; @@ -4868,6 +4875,9 @@ int zend_get_class_fetch_type(zend_uchar } else if ((class_name_len == sizeof("parent")-1) && ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) { return ZEND_FETCH_CLASS_PARENT; + } else if ((class_name_len == sizeof("static")-1) && + ZEND_U_EQUAL(type, class_name, class_name_len, "static", sizeof("static")-1)) { + return ZEND_FETCH_CLASS_STATIC; } else { return ZEND_FETCH_CLASS_DEFAULT; } Index: Zend/zend_compile.h =================================================================== RCS file: /repository/ZendEngine2/zend_compile.h,v retrieving revision 1.364 diff -u -p -d -r1.364 zend_compile.h --- Zend/zend_compile.h 24 Aug 2007 13:50:52 -0000 1.364 +++ Zend/zend_compile.h 24 Aug 2007 16:50:14 -0000 @@ -300,6 +300,7 @@ struct _zend_execute_data { struct _zend_op *opline; zend_function_state function_state; zend_function *fbc; /* Function Being Called */ + zend_class_entry *caller_scope; zend_op_array *op_array; zval *object; union _temp_variable *Ts; @@ -632,6 +633,7 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_FETCH_CLASS_GLOBAL 4 #define ZEND_FETCH_CLASS_AUTO 5 #define ZEND_FETCH_CLASS_INTERFACE 6 +#define ZEND_FETCH_CLASS_STATIC 7 #define ZEND_FETCH_CLASS_FLAGS 0xF0 #define ZEND_FETCH_CLASS_NO_NORMALIZE 0x10 #define ZEND_FETCH_CLASS_RT_NS_CHECK 0x20 Index: Zend/zend_constants.c =================================================================== RCS file: /repository/ZendEngine2/zend_constants.c,v retrieving revision 1.98 diff -u -p -d -r1.98 zend_constants.c --- Zend/zend_constants.c 24 Aug 2007 13:50:52 -0000 1.98 +++ Zend/zend_constants.c 24 Aug 2007 16:50:14 -0000 @@ -382,6 +382,14 @@ ZEND_API int zend_u_get_constant_ex(zend ce = &scope->parent; } efree(lcname.v); + } else if (lcname_len == sizeof("static")-1 && + ZEND_U_EQUAL(type, lcname, lcname_len, "static", sizeof("static")-1)) { + if (EG(caller_scope)) { + ce = &EG(caller_scope); + } else { + zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); + } + efree(lcname.v); } else { /* Check for namespace constant */ zstr nsname; Index: Zend/zend_execute_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute_API.c,v retrieving revision 1.413 diff -u -p -d -r1.413 zend_execute_API.c --- Zend/zend_execute_API.c 24 Aug 2007 13:50:52 -0000 1.413 +++ Zend/zend_execute_API.c 24 Aug 2007 16:50:14 -0000 @@ -201,6 +201,7 @@ void init_executor(TSRMLS_D) /* {{{ */ EG(exception) = NULL; EG(scope) = NULL; + EG(caller_scope) = NULL; EG(This) = NULL; @@ -677,6 +678,7 @@ int zend_call_function(zend_fcall_info * zend_op_array *original_op_array; zend_op **original_opline_ptr; zend_class_entry *current_scope; + zend_class_entry *current_caller_scope; zend_class_entry *calling_scope = NULL; zend_class_entry *check_scope_or_static = NULL; zval *current_this; @@ -785,6 +787,15 @@ int zend_call_function(zend_fcall_info * found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + } else if (Z_UNILEN_PP(fci->object_pp) == sizeof("static")-1 && + ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "static", sizeof("static")-1)) { + if (!EG(caller_scope)) { + zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); + } + ce = &(EG(caller_scope)); + found = (*ce != NULL?SUCCESS:FAILURE); + fci->object_pp = EG(This)?&EG(This):NULL; + EX(object) = EG(This); } else { zend_class_entry *scope; scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; @@ -853,6 +864,9 @@ int zend_call_function(zend_fcall_info * } else if (calling_scope && clen == sizeof("parent") - 1 && ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "parent", sizeof("parent")-1)) { ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL; + } else if (clen == sizeof("static") - 1 && + ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "static", sizeof("static")-1)) { + ce_child = EG(caller_scope); } else if (zend_u_lookup_class_ex(Z_TYPE_P(fci->function_name), lcname, clen, 1, 0, &pce TSRMLS_CC) == SUCCESS) { ce_child = *pce; } @@ -1029,6 +1043,16 @@ int zend_call_function(zend_fcall_info * current_this = EG(This); + current_caller_scope = EG(caller_scope); + if (calling_scope) { + if (!EG(caller_scope) || !EX(object) || + !instanceof_function(EG(caller_scope), calling_scope TSRMLS_CC)) { + EG(caller_scope) = calling_scope; + } + } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) { + EG(caller_scope) = NULL; + } + if (fci->object_pp) { if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) { EG(This) = NULL; @@ -1110,6 +1134,7 @@ int zend_call_function(zend_fcall_info * if (EG(This)) { zval_ptr_dtor(&EG(This)); } + EG(caller_scope) = current_caller_scope; EG(scope) = current_scope; EG(This) = current_this; EG(current_execute_data) = EX(prev_execute_data); @@ -1680,6 +1705,11 @@ check_fetch_type: zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); } return EG(scope)->parent; + case ZEND_FETCH_CLASS_STATIC: + if (!EG(caller_scope)) { + zend_error(E_ERROR, "Cannot access static:: when no class scope is active"); + } + return EG(caller_scope); case ZEND_FETCH_CLASS_AUTO: { if (do_normalize) { lcname = zend_u_str_case_fold(type, class_name, class_name_len, 1, &class_name_len); Index: Zend/zend_globals.h =================================================================== RCS file: /repository/ZendEngine2/zend_globals.h,v retrieving revision 1.168 diff -u -p -d -r1.168 zend_globals.h --- Zend/zend_globals.h 12 Jul 2007 09:23:48 -0000 1.168 +++ Zend/zend_globals.h 24 Aug 2007 16:50:14 -0000 @@ -185,6 +185,7 @@ struct _zend_executor_globals { HashTable *zend_constants; /* constants table */ zend_class_entry *scope; + zend_class_entry *caller_scope; /* Scope of the calling class */ zval *This; Index: Zend/zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.189 diff -u -p -d -r1.189 zend_language_parser.y --- Zend/zend_language_parser.y 24 Aug 2007 13:50:52 -0000 1.189 +++ Zend/zend_language_parser.y 24 Aug 2007 16:50:14 -0000 @@ -670,6 +670,7 @@ function_call: fully_qualified_class_name: T_STRING { $$ = $1; } + | T_STATIC { $$.op_type = IS_CONST; ZVAL_ASCII_STRINGL(&$$.u.constant, "static", sizeof("static")-1, 1);} | T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); } | fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); } ; Index: Zend/zend_ptr_stack.h =================================================================== RCS file: /repository/ZendEngine2/zend_ptr_stack.h,v retrieving revision 1.26 diff -u -p -d -r1.26 zend_ptr_stack.h --- Zend/zend_ptr_stack.h 1 Jan 2007 09:29:21 -0000 1.26 +++ Zend/zend_ptr_stack.h 24 Aug 2007 16:50:14 -0000 @@ -52,9 +52,9 @@ END_EXTERN_C() /* Not doing this with a macro because of the loop unrolling in the element assignment. Just using a macro for 3 in the body for readability sake. */ -static inline void zend_ptr_stack_3_push(zend_ptr_stack *stack, void *a, void *b, void *c) +static inline void zend_ptr_stack_4_push(zend_ptr_stack *stack, void *a, void *b, void *c, void *d) { -#define ZEND_PTR_STACK_NUM_ARGS 3 +#define ZEND_PTR_STACK_NUM_ARGS 4 ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, ZEND_PTR_STACK_NUM_ARGS) @@ -62,6 +62,7 @@ static inline void zend_ptr_stack_3_push *(stack->top_element++) = a; *(stack->top_element++) = b; *(stack->top_element++) = c; + *(stack->top_element++) = d; #undef ZEND_PTR_STACK_NUM_ARGS } Index: Zend/zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.179 diff -u -p -d -r1.179 zend_vm_def.h --- Zend/zend_vm_def.h 24 Aug 2007 13:50:52 -0000 1.179 +++ Zend/zend_vm_def.h 24 Aug 2007 16:50:15 -0000 @@ -1736,7 +1736,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CA /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -1763,6 +1763,8 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CA zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -1789,7 +1791,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_ME zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { /* try a function in namespace */ @@ -1848,6 +1850,13 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_ME EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -1862,6 +1871,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_ME } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -1877,7 +1887,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_N unsigned int function_name_strlen, lcname_len; zend_free_op free_op2; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (OP2_TYPE == IS_CONST) { function_name = &opline->op2.u.constant; @@ -1955,6 +1965,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_help zend_op *opline = EX(opline); zval **original_return_value; zend_class_entry *current_scope = NULL; + zend_class_entry *current_caller_scope; zval *current_this = NULL; int return_value_used = RETURN_VALUE_USED(opline); zend_bool should_change_scope; @@ -1991,6 +2002,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_help EX_T(opline->result.u.var).var.fcall_returned_reference = 0; + current_caller_scope = EG(caller_scope); if (EX(function_state).function->common.scope) { if (!EG(This) && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) { int severity; @@ -2005,7 +2017,11 @@ ZEND_VM_HELPER(zend_do_fcall_common_help /* FIXME: output identifiers properly */ zend_error(severity, "Non-static method %v::%v() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word); } + EG(caller_scope) = EX(caller_scope); + } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) { + EG(caller_scope) = NULL; } + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { unsigned char return_reference = EX(function_state).function->common.return_reference; @@ -2126,11 +2142,12 @@ ZEND_VM_HELPER(zend_do_fcall_common_help } } + EG(caller_scope) = current_caller_scope; if (should_change_scope) { EG(This) = current_this; EG(scope) = current_scope; } - zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc)); + zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(caller_scope), (void**)&EX(object), (void**)&EX(fbc)); EX(function_state).function = (zend_function *) EX(op_array); EG(function_state_ptr) = &EX(function_state); @@ -2158,7 +2175,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST zend_free_op free_op1; zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) { /* FIXME: output identifiers properly */ @@ -2629,11 +2646,12 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY) EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; EX_T(opline->result.u.var).var.ptr = object_zval; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), opline); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), opline); /* We are not handling overloaded classes right now */ EX(object) = object_zval; EX(fbc) = constructor; + EX(caller_scope) = EX_T(opline->op1.u.var).class_entry; ZEND_VM_NEXT_OPCODE(); } @@ -4030,7 +4048,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTI } zval_ptr_dtor(&EX(object)); } - zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc)); + zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(caller_scope), (void**)&EX(object), (void**)&EX(fbc)); } for (i=0; i<EX(op_array)->last_brk_cont; i++) { Index: Zend/zend_vm_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.h,v retrieving revision 1.183 diff -u -p -d -r1.183 zend_vm_execute.h --- Zend/zend_vm_execute.h 24 Aug 2007 13:50:52 -0000 1.183 +++ Zend/zend_vm_execute.h 24 Aug 2007 16:50:17 -0000 @@ -42,6 +42,7 @@ ZEND_API void execute(zend_op_array *op_ /* Initialize execute_data */ EX(fbc) = NULL; + EX(caller_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; if (op_array->T < TEMP_VAR_STACK_LIMIT) { @@ -134,6 +135,7 @@ static int zend_do_fcall_common_helper_S zend_op *opline = EX(opline); zval **original_return_value; zend_class_entry *current_scope = NULL; + zend_class_entry *current_caller_scope; zval *current_this = NULL; int return_value_used = RETURN_VALUE_USED(opline); zend_bool should_change_scope; @@ -170,6 +172,7 @@ static int zend_do_fcall_common_helper_S EX_T(opline->result.u.var).var.fcall_returned_reference = 0; + current_caller_scope = EG(caller_scope); if (EX(function_state).function->common.scope) { if (!EG(This) && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) { int severity; @@ -184,7 +187,11 @@ static int zend_do_fcall_common_helper_S /* FIXME: output identifiers properly */ zend_error(severity, "Non-static method %v::%v() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word); } + EG(caller_scope) = EX(caller_scope); + } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) { + EG(caller_scope) = NULL; } + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { unsigned char return_reference = EX(function_state).function->common.return_reference; @@ -305,11 +312,12 @@ static int zend_do_fcall_common_helper_S } } + EG(caller_scope) = current_caller_scope; if (should_change_scope) { EG(This) = current_this; EG(scope) = current_scope; } - zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc)); + zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(caller_scope), (void**)&EX(object), (void**)&EX(fbc)); EX(function_state).function = (zend_function *) EX(op_array); EG(function_state_ptr) = &EX(function_state); @@ -431,11 +439,12 @@ static int ZEND_NEW_SPEC_HANDLER(ZEND_OP EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; EX_T(opline->result.u.var).var.ptr = object_zval; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), opline); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), opline); /* We are not handling overloaded classes right now */ EX(object) = object_zval; EX(fbc) = constructor; + EX(caller_scope) = EX_T(opline->op1.u.var).class_entry; ZEND_VM_NEXT_OPCODE(); } @@ -572,7 +581,7 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HA } zval_ptr_dtor(&EX(object)); } - zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc)); + zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(caller_scope), (void**)&EX(object), (void**)&EX(fbc)); } for (i=0; i<EX(op_array)->last_brk_cont; i++) { @@ -676,7 +685,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ unsigned int function_name_strlen, lcname_len; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CONST == IS_CONST) { function_name = &opline->op2.u.constant; @@ -874,7 +883,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ unsigned int function_name_strlen, lcname_len; zend_free_op free_op2; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_TMP_VAR == IS_CONST) { function_name = &opline->op2.u.constant; @@ -987,7 +996,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ unsigned int function_name_strlen, lcname_len; zend_free_op free_op2; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_VAR == IS_CONST) { function_name = &opline->op2.u.constant; @@ -1129,7 +1138,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_ unsigned int function_name_strlen, lcname_len; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CV == IS_CONST) { function_name = &opline->op2.u.constant; @@ -1501,7 +1510,7 @@ static int ZEND_DO_FCALL_SPEC_CONST_HAND zval *fname = &opline->op1.u.constant; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) { /* FIXME: output identifiers properly */ @@ -2541,7 +2550,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CONST == IS_CONST && IS_CONST == IS_CONST) { /* try a function in namespace */ @@ -2600,6 +2609,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -2614,6 +2630,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -3084,7 +3101,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CONST == IS_CONST && IS_TMP_VAR == IS_CONST) { /* try a function in namespace */ @@ -3143,6 +3160,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3157,6 +3181,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -3529,7 +3554,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CONST == IS_CONST && IS_VAR == IS_CONST) { /* try a function in namespace */ @@ -3588,6 +3613,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3602,6 +3634,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -3740,7 +3773,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST) { /* try a function in namespace */ @@ -3799,6 +3832,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -3813,6 +3853,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -4153,7 +4194,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_CONST == IS_CONST && IS_CV == IS_CONST) { /* try a function in namespace */ @@ -4212,6 +4253,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -4226,6 +4274,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -5750,7 +5799,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = &opline->op2.u.constant; @@ -5777,6 +5826,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -6199,7 +6250,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -6226,6 +6277,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -6650,7 +6703,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -6677,6 +6730,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -7194,7 +7249,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -7221,6 +7276,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -9946,7 +10003,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = &opline->op2.u.constant; @@ -9973,6 +10030,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -9998,7 +10057,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) { /* try a function in namespace */ @@ -10057,6 +10116,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -10071,6 +10137,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -11635,7 +11702,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -11662,6 +11729,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -11688,7 +11757,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_VAR == IS_CONST && IS_TMP_VAR == IS_CONST) { /* try a function in namespace */ @@ -11747,6 +11816,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -11761,6 +11837,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -13303,7 +13380,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -13330,6 +13407,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -13356,7 +13435,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_VAR == IS_CONST && IS_VAR == IS_CONST) { /* try a function in namespace */ @@ -13415,6 +13494,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -13429,6 +13515,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -14222,7 +14309,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST) { /* try a function in namespace */ @@ -14281,6 +14368,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -14295,6 +14389,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -15488,7 +15583,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -15515,6 +15610,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -15540,7 +15637,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ zval *function_name; zend_class_entry *ce; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); if (IS_VAR == IS_CONST && IS_CV == IS_CONST) { /* try a function in namespace */ @@ -15599,6 +15696,13 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ EX(fbc) = ce->constructor; } + if (EG(caller_scope) && + instanceof_function(EG(caller_scope), ce TSRMLS_CC)) { + EX(caller_scope) = EG(caller_scope); + } else { + EX(caller_scope) = ce; + } + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -15613,6 +15717,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_ } if ((EX(object) = EG(This))) { EX(object)->refcount++; + EX(caller_scope) = Z_OBJCE_P(EX(object)); } } @@ -16785,7 +16890,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = &opline->op2.u.constant; @@ -16812,6 +16917,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -17862,7 +17969,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -17889,6 +17996,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -18879,7 +18988,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -18906,6 +19015,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -20161,7 +20272,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -20188,6 +20299,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -22931,7 +23044,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = &opline->op2.u.constant; @@ -22958,6 +23071,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -24466,7 +24581,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -24493,6 +24608,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -26040,7 +26157,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC); @@ -26067,6 +26184,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -28045,7 +28164,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL); + zend_ptr_stack_4_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(caller_scope), NULL); function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC); @@ -28072,6 +28191,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } + EX(caller_scope) = Z_OBJCE_P(EX(object)); + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { Index: Zend/zend_vm_execute.skl =================================================================== RCS file: /repository/ZendEngine2/zend_vm_execute.skl,v retrieving revision 1.7 diff -u -p -d -r1.7 zend_vm_execute.skl --- Zend/zend_vm_execute.skl 21 Jul 2007 00:34:41 -0000 1.7 +++ Zend/zend_vm_execute.skl 24 Aug 2007 16:50:17 -0000 @@ -13,6 +13,7 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_ /* Initialize execute_data */ EX(fbc) = NULL; + EX(caller_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; if (op_array->T < TEMP_VAR_STACK_LIMIT) {
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php