Attached.
Thanks. Dmitry.
> -----Original Message-----
> From: Etienne Kneuss [mailto:[EMAIL PROTECTED]
> Sent: Sunday, September 09, 2007 11:02 PM
> To: Dmitry Stogov
> Cc: [email protected]
> Subject: Re: [PHP-DEV] [patch] Late static bindings (LSB)
>
>
> Hello,
>
> sorry for the late reply, I am on vacations these weeks and
> only have a
> sparse access to web.
> I was aware that my patch missed supports for callbacks, and
> let it that
> way on purpose as I
> planned to do some cleanup work on callbacks.
>
> It looks like you placed the work necessary to have LSB in a
> different
> place than mine,
> generating more occurences and hence a quite bigger patch
> size. I'd like
> to see what implications it has.
>
> Sadly, the patch you gave me is not easily patchable with the current
> HEAD, do you have an up to date version ?
>
> Thanks in advance
>
> Dmitry Stogov wrote:
> > 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: [email protected]
> >> 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
> >>
> >>
> >>
>
>
> --
> Etienne Kneuss
> http://www.colder.ch
>
> Men never do evil so completely and cheerfully as
> when they do it from a religious conviction.
> -- Pascal
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
Index: Zend/zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.443
diff -u -p -d -r1.443 zend_API.c
--- Zend/zend_API.c 31 Aug 2007 12:36:00 -0000 1.443
+++ Zend/zend_API.c 10 Sep 2007 07:59:35 -0000
@@ -2860,6 +2860,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.350
diff -u -p -d -r1.350 zend_builtin_functions.c
--- Zend/zend_builtin_functions.c 30 Aug 2007 07:43:53 -0000 1.350
+++ Zend/zend_builtin_functions.c 10 Sep 2007 07:59:35 -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.767
diff -u -p -d -r1.767 zend_compile.c
--- Zend/zend_compile.c 5 Sep 2007 07:24:52 -0000 1.767
+++ Zend/zend_compile.c 10 Sep 2007 07:59:36 -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];
@@ -4876,6 +4883,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 10 Sep 2007 07:59:36 -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.99
diff -u -p -d -r1.99 zend_constants.c
--- Zend/zend_constants.c 25 Aug 2007 23:28:10 -0000 1.99
+++ Zend/zend_constants.c 10 Sep 2007 07:59:36 -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.414
diff -u -p -d -r1.414 zend_execute_API.c
--- Zend/zend_execute_API.c 30 Aug 2007 14:48:39 -0000 1.414
+++ Zend/zend_execute_API.c 10 Sep 2007 07:59:36 -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 10 Sep 2007 07:59:36 -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 10 Sep 2007 07:59:36 -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 10 Sep 2007 07:59:36 -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.181
diff -u -p -d -r1.181 zend_vm_def.h
--- Zend/zend_vm_def.h 7 Sep 2007 09:31:26 -0000 1.181
+++ Zend/zend_vm_def.h 10 Sep 2007 07:59:36 -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 */
@@ -1850,6 +1852,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 {
@@ -1864,6 +1873,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));
}
}
@@ -1879,7 +1889,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;
@@ -1957,6 +1967,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;
@@ -1993,6 +2004,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;
@@ -2007,7 +2019,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;
@@ -2128,11 +2144,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);
@@ -2160,7 +2177,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 */
@@ -2631,11 +2648,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();
}
@@ -4032,7 +4050,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.185
diff -u -p -d -r1.185 zend_vm_execute.h
--- Zend/zend_vm_execute.h 7 Sep 2007 09:31:26 -0000 1.185
+++ Zend/zend_vm_execute.h 10 Sep 2007 07:59:36 -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 */
@@ -2602,6 +2611,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 {
@@ -2616,6 +2632,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -3086,7 +3103,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 */
@@ -3147,6 +3164,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 {
@@ -3161,6 +3185,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -3533,7 +3558,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 */
@@ -3594,6 +3619,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 {
@@ -3608,6 +3640,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -3746,7 +3779,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 */
@@ -3807,6 +3840,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 {
@@ -3821,6 +3861,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -4161,7 +4202,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 */
@@ -4222,6 +4263,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 {
@@ -4236,6 +4284,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -5760,7 +5809,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;
@@ -5787,6 +5836,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 {
@@ -6209,7 +6260,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);
@@ -6236,6 +6287,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 {
@@ -6660,7 +6713,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);
@@ -6687,6 +6740,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 {
@@ -7204,7 +7259,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);
@@ -7231,6 +7286,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 {
@@ -9956,7 +10013,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;
@@ -9983,6 +10040,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 {
@@ -10008,7 +10067,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 */
@@ -10069,6 +10128,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 {
@@ -10083,6 +10149,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -11647,7 +11714,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);
@@ -11674,6 +11741,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 {
@@ -11700,7 +11769,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 */
@@ -11761,6 +11830,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 {
@@ -11775,6 +11851,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -13317,7 +13394,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);
@@ -13344,6 +13421,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 {
@@ -13370,7 +13449,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 */
@@ -13431,6 +13510,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 {
@@ -13445,6 +13531,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -14238,7 +14325,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 */
@@ -14299,6 +14386,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 {
@@ -14313,6 +14407,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -15506,7 +15601,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);
@@ -15533,6 +15628,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 {
@@ -15558,7 +15655,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 */
@@ -15619,6 +15716,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 {
@@ -15633,6 +15737,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
+ EX(caller_scope) = Z_OBJCE_P(EX(object));
}
}
@@ -16805,7 +16910,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;
@@ -16832,6 +16937,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 {
@@ -17882,7 +17989,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);
@@ -17909,6 +18016,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 {
@@ -18899,7 +19008,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);
@@ -18926,6 +19035,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 {
@@ -20181,7 +20292,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);
@@ -20208,6 +20319,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 {
@@ -22951,7 +23064,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;
@@ -22978,6 +23091,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 {
@@ -24486,7 +24601,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);
@@ -24513,6 +24628,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 {
@@ -26060,7 +26177,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);
@@ -26087,6 +26204,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 {
@@ -28065,7 +28184,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);
@@ -28092,6 +28211,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 10 Sep 2007 07:59:36 -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