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

Reply via email to