Added support for Late Static Binding. (Dmitry, Etienne Kneuss)

This commit is contained in:
Dmitry Stogov 2007-09-29 07:28:34 +00:00
parent e9dd6fab91
commit 166266df68
30 changed files with 861 additions and 162 deletions

1
NEWS
View File

@ -2,6 +2,7 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 20??, PHP 5.3.0
- Added support for namespaces. (Dmitry, Stas)
- Added support for Late Static Binding. (Dmitry, Etienne Kneuss)
- Added support for dynamic access of static members using $foo::myFunc().
(Etienne Kneuss)

61
Zend/tests/lsb_001.phpt Normal file
View File

@ -0,0 +1,61 @@
--TEST--
ZE2 Late Static Binding in a static function
--FILE--
<?php
class TestClass {
protected static $staticVar = 'TestClassStatic';
const CLASS_CONST = 'TestClassConst';
protected static function staticFunction() {
return 'TestClassFunction';
}
public static function testStaticVar() {
return static::$staticVar;
}
public static function testClassConst() {
return static::CLASS_CONST;
}
public static function testStaticFunction() {
return static::staticFunction();
}
}
class ChildClass1 extends TestClass {
protected static $staticVar = 'ChildClassStatic';
const CLASS_CONST = 'ChildClassConst';
protected static function staticFunction() {
return 'ChildClassFunction';
}
}
class ChildClass2 extends TestClass {}
echo TestClass::testStaticVar() . "\n";
echo TestClass::testClassConst() . "\n";
echo TestClass::testStaticFunction() . "\n";
echo ChildClass1::testStaticVar() . "\n";
echo ChildClass1::testClassConst() . "\n";
echo ChildClass1::testStaticFunction() . "\n";
echo ChildClass2::testStaticVar() . "\n";
echo ChildClass2::testClassConst() . "\n";
echo ChildClass2::testStaticFunction() . "\n";
?>
==DONE==
--EXPECTF--
TestClassStatic
TestClassConst
TestClassFunction
ChildClassStatic
ChildClassConst
ChildClassFunction
TestClassStatic
TestClassConst
TestClassFunction
==DONE==

66
Zend/tests/lsb_002.phpt Normal file
View File

@ -0,0 +1,66 @@
--TEST--
ZE2 Late Static Binding in an instance function
--FILE--
<?php
class TestClass {
protected static $staticVar = 'TestClassStatic';
const CLASS_CONST = 'TestClassConst';
protected static function staticFunction() {
return 'TestClassFunction';
}
public function testStaticVar() {
return static::$staticVar;
}
public function testClassConst() {
return static::CLASS_CONST;
}
public function testStaticFunction() {
return static::staticFunction();
}
}
class ChildClass1 extends TestClass {
protected static $staticVar = 'ChildClassStatic';
const CLASS_CONST = 'ChildClassConst';
protected static function staticFunction() {
return 'ChildClassFunction';
}
}
class ChildClass2 extends TestClass {}
$testClass = new TestClass();
$childClass1 = new ChildClass1();
$childClass2 = new ChildClass2();
echo $testClass->testStaticVar() . "\n";
echo $testClass->testClassConst() . "\n";
echo $testClass->testStaticFunction() . "\n";
echo $childClass1->testStaticVar() . "\n";
echo $childClass1->testClassConst() . "\n";
echo $childClass1->testStaticFunction() . "\n";
echo $childClass2->testStaticVar() . "\n";
echo $childClass2->testClassConst() . "\n";
echo $childClass2->testStaticFunction() . "\n";
?>
==DONE==
--EXPECTF--
TestClassStatic
TestClassConst
TestClassFunction
ChildClassStatic
ChildClassConst
ChildClassFunction
TestClassStatic
TestClassConst
TestClassFunction
==DONE==

24
Zend/tests/lsb_003.phpt Normal file
View File

@ -0,0 +1,24 @@
--TEST--
ZE2 Late Static Binding creating a new class with 'static'
--FILE--
<?php
class TestClass {
public static function createInstance() {
return new static();
}
}
class ChildClass extends TestClass {}
$testClass = TestClass::createInstance();
$childClass = ChildClass::createInstance();
echo get_class($testClass) . "\n";
echo get_class($childClass) . "\n";
?>
==DONE==
--EXPECTF--
TestClass
ChildClass
==DONE==

21
Zend/tests/lsb_004.phpt Normal file
View File

@ -0,0 +1,21 @@
--TEST--
ZE2 Late Static Binding testing get_called_class()
--FILE--
<?php
class TestClass {
public static function getClassName() {
return get_called_class();
}
}
class ChildClass extends TestClass {}
echo TestClass::getClassName() . "\n";
echo ChildClass::getClassName() . "\n";
?>
==DONE==
--EXPECTF--
TestClass
ChildClass
==DONE==

51
Zend/tests/lsb_005.phpt Normal file
View File

@ -0,0 +1,51 @@
--TEST--
ZE2 Late Static Binding stacking static calleds
--FILE--
<?php
class TestA {
public static function test() {
echo get_class(new static()) . "\n";
TestB::test();
echo get_class(new static()) . "\n";
TestC::test();
echo get_class(new static()) . "\n";
TestBB::test();
echo get_class(new static()) . "\n";
}
}
class TestB {
public static function test() {
echo get_class(new static()) . "\n";
TestC::test();
echo get_class(new static()) . "\n";
}
}
class TestC {
public static function test() {
echo get_class(new static()) . "\n";
}
}
class TestBB extends TestB {
}
TestA::test();
?>
==DONE==
--EXPECTF--
TestA
TestB
TestC
TestB
TestA
TestC
TestA
TestBB
TestC
TestBB
TestA
==DONE==

12
Zend/tests/lsb_006.phpt Normal file
View File

@ -0,0 +1,12 @@
--TEST--
ZE2 Late Static Binding ensuring extending 'static' is not allowed
--FILE--
<?php
class Foo extends static {
}
?>
==DONE==
--EXPECTF--
Fatal error: Cannot use 'static' as class name as it is reserved in %s on line %d

12
Zend/tests/lsb_007.phpt Normal file
View File

@ -0,0 +1,12 @@
--TEST--
ZE2 Late Static Binding ensuring implementing 'static' is not allowed
--FILE--
<?php
class Foo implements static {
}
?>
==DONE==
--EXPECTF--
Fatal error: Cannot use 'static' as interface name as it is reserved in %s on line %d

8
Zend/tests/lsb_008.phpt Normal file
View File

@ -0,0 +1,8 @@
--TEST--
ZE2 Late Static Binding class name "static"
--FILE--
<?php
class static {
}
--EXPECTF--
Parse error: syntax error, unexpected T_STATIC, expecting T_STRING in %slsb_008.php on line 2

8
Zend/tests/lsb_009.phpt Normal file
View File

@ -0,0 +1,8 @@
--TEST--
ZE2 Late Static Binding interface name "static"
--FILE--
<?php
interface static {
}
--EXPECTF--
Parse error: syntax error, unexpected T_STATIC, expecting T_STRING in %slsb_009.php on line 2

38
Zend/tests/lsb_010.phpt Normal file
View File

@ -0,0 +1,38 @@
--TEST--
ZE2 Late Static Binding using static:: in functions called by non execute() calls and constructors.
--FILE--
<?php
class Foo {
protected static $className = 'Foo';
public static function bar() {
echo static::$className . "::bar\n";
}
public function __construct() {
echo static::$className . "::__construct\n";
}
public function __destruct() {
echo static::$className . "::__destruct\n";
}
}
class FooChild extends Foo {
protected static $className = 'FooChild';
}
register_shutdown_function(array('Foo', 'bar'));
register_shutdown_function(array('FooChild', 'bar'));
$foo = new Foo();
$fooChild = new FooChild();
unset($foo);
unset($fooChild);
?>
--EXPECTF--
Foo::__construct
FooChild::__construct
Foo::__destruct
FooChild::__destruct
Foo::bar
FooChild::bar

23
Zend/tests/lsb_011.phpt Normal file
View File

@ -0,0 +1,23 @@
--TEST--
ZE2 Late Static Binding call to static::method() from internal function (array)
--FILE--
<?php
class Test1 {
static function ok() {
echo "bug";
}
static function test() {
call_user_func(array("static","ok"));
}
}
class Test2 extends Test1 {
static function ok() {
echo "ok";
}
}
Test2::test();
?>
--EXPECT--
ok

23
Zend/tests/lsb_012.phpt Normal file
View File

@ -0,0 +1,23 @@
--TEST--
ZE2 Late Static Binding call to static::method() from internal function (string)
--FILE--
<?php
class Test1 {
static function ok() {
echo "bug";
}
static function test() {
call_user_func("static::ok");
}
}
class Test2 extends Test1 {
static function ok() {
echo "ok";
}
}
Test2::test();
?>
--EXPECT--
ok

24
Zend/tests/lsb_013.phpt Normal file
View File

@ -0,0 +1,24 @@
--TEST--
ZE2 Late Static Binding is_callable() and static::method()
--FILE--
<?php
class Test1 {
static function test() {
var_dump(is_callable("static::ok"));
var_dump(is_callable(array("static","ok")));
}
}
class Test2 extends Test1 {
static function ok() {
}
}
Test1::test();
Test2::test();
?>
--EXPECT--
bool(false)
bool(false)
bool(true)
bool(true)

24
Zend/tests/lsb_014.phpt Normal file
View File

@ -0,0 +1,24 @@
--TEST--
ZE2 Late Static Binding access to static::const through defined() anf get_constant()
--FILE--
<?php
class Test1 {
static function test() {
var_dump(defined("static::ok"));
if (defined("static::ok")) {
echo constant("static::ok");
}
}
}
class Test2 extends Test1 {
const ok = "ok";
}
Test1::test();
Test2::test();
?>
--EXPECT--
bool(false)
bool(true)
ok

92
Zend/tests/lsb_015.phpt Normal file
View File

@ -0,0 +1,92 @@
--TEST--
ZE2 Late Static Binding with exceptions
--FILE--
<?php
function foo() {
B::throwException();
}
class C {
public static function bla() {
B::throwException();
}
public static function getException() {
return new Exception();
}
}
class A {
public static function throwException_after() {
C::bla();
}
public static function throwException() {
throw C::getException();
}
public static function test() {
static::who();
}
public static function who() {
echo "A\n";
}
public static function mycatch() {
try {
static::who();
B::throwException_after();
} catch(Exception $e) {
static::who();
A::test();
static::who();
B::test();
static::who();
self::simpleCatch();
static::who();
}
}
public static function simpleCatch() {
try {
static::who();
throw new Exception();
} catch (Exception $e) {
static::who();
}
}
}
class B extends A {
public static function who() {
echo "B\n";
}
}
echo "via A:\n";
A::myCatch();
echo "via B:\n";
B::myCatch();
?>
==DONE==
--EXPECTF--
via A:
A
A
A
A
B
A
A
A
A
via B:
B
B
A
B
B
B
A
A
B
==DONE==

41
Zend/tests/lsb_016.phpt Normal file
View File

@ -0,0 +1,41 @@
--TEST--
ZE2 Late Static Binding within hooks/magic methods
--FILE--
<?php
class TestChild extends TestParent {
public static function who() {
echo __CLASS__."\n";
}
}
class TestParent {
public function __get($var) {
static::who();
}
public function __set($var, $val) {
static::who();
}
public function __call($name, $args) {
static::who();
}
public static function who() {
echo __CLASS__."\n";
}
}
$o = new TestChild;
$o->test();
$o->a = "b";
echo $o->a;
?>
==DONE==
--EXPECTF--
TestChild
TestChild
TestChild
==DONE==

29
Zend/tests/lsb_017.phpt Normal file
View File

@ -0,0 +1,29 @@
--TEST--
ZE2 Late Static Binding nested calls
--FILE--
<?php
class A {
public static function test($x=null) {
if (!is_null($x)) {
echo "$x\n";
}
return get_called_class();
}
}
class B extends A {
}
class C extends A {
}
class D extends A {
}
echo A::test(B::test(C::test(D::test())))."\n";
?>
==DONE==
--EXPECT--
D
C
B
A
==DONE==

View File

@ -2306,10 +2306,13 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
}
lcname = zend_str_tolower_dup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
if (Z_STRLEN_PP(obj) == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self")) == 0 && EG(active_op_array)) {
if (Z_STRLEN_PP(obj) == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self")-1) == 0 && EG(active_op_array)) {
ce = EG(active_op_array)->scope;
} else if (Z_STRLEN_PP(obj) == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent")) == 0 && EG(active_op_array) && EG(active_op_array)->scope) {
} else if (Z_STRLEN_PP(obj) == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent")-1) == 0 && EG(active_op_array) && EG(active_op_array)->scope) {
ce = EG(active_op_array)->scope->parent;
} else if (Z_STRLEN_PP(obj) == sizeof("static")-1 &&
!memcmp(lcname, "static", sizeof("static")-1)) {
ce = EG(called_scope);
} else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
}

View File

@ -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_called_class);
static ZEND_FUNCTION(get_parent_class);
static ZEND_FUNCTION(method_exists);
static ZEND_FUNCTION(property_exists);
@ -103,6 +104,7 @@ static const zend_function_entry builtin_functions[] = {
ZEND_FE(define, NULL)
ZEND_FE(defined, NULL)
ZEND_FE(get_class, NULL)
ZEND_FE(get_called_class, NULL)
ZEND_FE(get_parent_class, NULL)
ZEND_FE(method_exists, NULL)
ZEND_FE(property_exists, NULL)
@ -584,6 +586,25 @@ ZEND_FUNCTION(get_class)
/* }}} */
/* {{{ proto string get_called_class()
Retrieves the "Late Static Binding" class name */
ZEND_FUNCTION(get_called_class)
{
if (!ZEND_NUM_ARGS()) {
if (EG(called_scope)) {
RETURN_STRINGL(EG(called_scope)->name, EG(called_scope)->name_length, 1);
} else {
zend_error(E_WARNING, "get_called_class() called from outside a class");
RETURN_FALSE;
}
} else {
ZEND_WRONG_PARAM_COUNT();
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto string get_parent_class([mixed object])
Retrieves the parent class name for object or class or current scope. */
ZEND_FUNCTION(get_parent_class)

View File

@ -1564,6 +1564,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
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);
@ -3008,6 +3009,9 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
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;
}
@ -3115,6 +3119,9 @@ void zend_do_implements_interface(znode *interface_name TSRMLS_DC)
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];
@ -4499,6 +4506,9 @@ int zend_get_class_fetch_type(const char *class_name, uint class_name_len)
} else if ((class_name_len == sizeof("parent")-1) &&
!memcmp(class_name, "parent", sizeof("parent")-1)) {
return ZEND_FETCH_CLASS_PARENT;
} else if ((class_name_len == sizeof("static")-1) &&
!memcmp(class_name, "static", sizeof("static")-1)) {
return ZEND_FETCH_CLASS_STATIC;
} else {
return ZEND_FETCH_CLASS_DEFAULT;
}

View File

@ -270,9 +270,7 @@ typedef union _zend_function {
typedef struct _zend_function_state {
HashTable *function_symbol_table;
zend_function *function;
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
} zend_function_state;
@ -295,6 +293,7 @@ struct _zend_execute_data {
struct _zend_op *opline;
zend_function_state function_state;
zend_function *fbc; /* Function Being Called */
zend_class_entry *called_scope;
zend_op_array *op_array;
zval *object;
union _temp_variable *Ts;
@ -597,6 +596,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_RT_NS_CHECK 0x20
#define ZEND_FETCH_CLASS_RT_NS_NAME 0x40
#define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80

View File

@ -317,6 +317,14 @@ ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_
ce = scope->parent;
}
efree(lcname);
} else if (class_name_len == sizeof("static")-1 &&
!memcmp(lcname, "static", sizeof("static")-1)) {
if (EG(called_scope)) {
ce = EG(called_scope);
} else {
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
}
efree(lcname);
} else {
/* Check for namespace constant */
char *nsname;

View File

@ -147,6 +147,17 @@ static inline void zend_pzval_unlock_free_func(zval *z)
#define CV_OF(i) (EG(current_execute_data)->CVs[i])
#define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
#define CTOR_CALL_BIT 0x1
#define CTOR_USED_BIT 0x2
#define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
#define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
#define ENCODE_CTOR(ce, used) \
((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
#define DECODE_CTOR(ce) \
((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data_ptr, zend_uint var)
{
return execute_data_ptr->CVs[var];

View File

@ -186,6 +186,7 @@ void init_executor(TSRMLS_D)
EG(exception) = NULL;
EG(scope) = NULL;
EG(called_scope) = NULL;
EG(This) = NULL;
@ -627,6 +628,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_op_array *original_op_array;
zend_op **original_opline_ptr;
zend_class_entry *current_scope;
zend_class_entry *current_called_scope;
zend_class_entry *calling_scope = NULL;
zend_class_entry *check_scope_or_static = NULL;
zval *current_this;
@ -729,6 +731,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
found = (*ce != NULL?SUCCESS:FAILURE);
fci->object_pp = EG(This)?&EG(This):NULL;
EX(object) = EG(This);
} else if (Z_STRLEN_PP(fci->object_pp) == sizeof("static")-1 &&
!memcmp(Z_STRVAL_PP(fci->object_pp), "static", sizeof("static")-1)) {
if (!EG(called_scope)) {
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
}
ce = &(EG(called_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;
@ -777,28 +788,24 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_hash_find(fci->function_table, lcname, fname_len+1, (void**)&EX(function_state).function) == SUCCESS) {
efree(lcname);
} else {
efree(lcname);
if ((colon = zend_memrchr(fname, ':', fname_len)) != NULL &&
colon > fname &&
*(colon-1) == ':') {
int clen = colon - fname - 1;
int mlen = fname_len - clen - 2;
zend_class_entry **pce, *ce_child = NULL;
if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
if (calling_scope && clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
} else if (calling_scope && clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
} else if (clen == sizeof("static") - 1 &&
!memcmp(lcname, "static", sizeof("static")-1)) {
ce_child = EG(called_scope);
} else if (zend_lookup_class(fname, clen, &pce TSRMLS_CC) == SUCCESS) {
ce_child = *pce;
} else {
char *lcname = zend_str_tolower_dup(fname, clen);
/* caution: lcname is not '\0' terminated */
if (calling_scope) {
if (clen == sizeof("self") - 1 && memcmp(lcname, "self", sizeof("self") - 1) == 0) {
ce_child = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
} else if (clen == sizeof("parent") - 1 && memcmp(lcname, "parent", sizeof("parent") - 1) == 0 && EG(active_op_array)->scope) {
ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL;
}
}
efree(lcname);
}
if (!ce_child) {
zend_error(E_ERROR, "Cannot call method %s() or method does not exist", fname);
return FAILURE;
@ -809,6 +816,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
fname = fname + clen + 2;
fname_len = mlen;
}
efree(lcname);
if (fci->object_pp) {
if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
@ -947,6 +955,13 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
current_this = EG(This);
current_called_scope = EG(called_scope);
if (calling_scope) {
EG(called_scope) = calling_scope;
} else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
EG(called_scope) = NULL;
}
if (fci->object_pp) {
if ((EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
EG(This) = NULL;
@ -1023,6 +1038,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
if (EG(This)) {
zval_ptr_dtor(&EG(This));
}
EG(called_scope) = current_called_scope;
EG(scope) = current_scope;
EG(This) = current_this;
EG(current_execute_data) = EX(prev_execute_data);
@ -1508,6 +1524,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(called_scope)) {
zend_error(E_ERROR, "Cannot access static:: when no class scope is active");
}
return EG(called_scope);
case ZEND_FETCH_CLASS_AUTO: {
fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {

View File

@ -190,6 +190,7 @@ struct _zend_executor_globals {
HashTable *zend_constants; /* constants table */
zend_class_entry *scope;
zend_class_entry *called_scope; /* Scope of the calling class */
zval *This;

View File

@ -661,6 +661,7 @@ function_call:
fully_qualified_class_name:
T_STRING { $$ = $1; }
| T_STATIC { $$.op_type = IS_CONST; ZVAL_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); }
;

View File

@ -1683,7 +1683,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
int function_name_strlen;
zend_free_op free_op1, free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
@ -1710,6 +1710,8 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -1736,7 +1738,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
/* try a function in namespace */
@ -1792,6 +1794,8 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -1806,6 +1810,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -1821,7 +1826,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (OP2_TYPE == IS_CONST) {
function_name_strval = opline->op2.u.constant.value.str.val;
@ -1878,11 +1883,12 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
{
zend_op *opline = EX(opline);
zval **original_return_value;
zend_class_entry *current_scope = NULL;
zval *current_this = NULL;
zend_class_entry *current_scope;
zend_class_entry *current_called_scope;
zval *current_this;
int return_value_used = RETURN_VALUE_USED(opline);
zend_bool should_change_scope;
zend_op *ctor_opline;
zval *ex_object;
if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
@ -1896,41 +1902,39 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
EX(function_state).function->common.function_name);
}
}
if (EX(function_state).function->common.scope &&
!(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) &&
!EX(object)) {
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
} else {
/* FIXME: output identifiers properly */
zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
}
}
zend_ptr_stack_2_push(&EG(argument_stack), (void *)(zend_uintptr_t)opline->extended_value, NULL);
EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
if (EX(function_state).function->type == ZEND_USER_FUNCTION
|| EX(function_state).function->common.scope) {
if (EX(function_state).function->type == ZEND_USER_FUNCTION ||
EX(function_state).function->common.scope) {
should_change_scope = 1;
current_this = EG(This);
EG(This) = EX(object);
current_scope = EG(scope);
current_called_scope = EG(called_scope);
EG(This) = EX(object);
EG(scope) = (EX(function_state).function->type == ZEND_USER_FUNCTION || !EX(object)) ? EX(function_state).function->common.scope : NULL;
EG(called_scope) = EX(called_scope);
} else {
should_change_scope = 0;
}
EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(called_scope), (void**)&ex_object, (void**)&EX(fbc));
zend_ptr_stack_2_push(&EG(argument_stack), (void *)(zend_uintptr_t)opline->extended_value, NULL);
EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
// EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
if (EX(function_state).function->common.scope) {
if (!EG(This) && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
int severity;
char *severity_word;
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
severity = E_STRICT;
severity_word = "should not";
} else {
severity = E_ERROR;
severity_word = "cannot";
}
zend_error(severity, "Non-static method %s::%s() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
}
}
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
unsigned char return_reference = EX(function_state).function->common.return_reference;
ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
INIT_ZVAL(*(EX_T(opline->result.u.var).var.ptr));
@ -1966,21 +1970,23 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (!return_value_used) {
zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
} else {
EX_T(opline->result.u.var).var.fcall_returned_reference = return_reference;
EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference;
}
} else if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
HashTable *function_symbol_table;
EX_T(opline->result.u.var).var.ptr = NULL;
if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--);
function_symbol_table = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EX(function_state).function_symbol_table);
zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
ALLOC_HASHTABLE(function_symbol_table);
zend_hash_init(function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
/*printf("Cache miss! Initialized %x\n", function_symbol_table);*/
}
EG(active_symbol_table) = EX(function_state).function_symbol_table;
EG(active_symbol_table) = function_symbol_table;
original_return_value = EG(return_value_ptr_ptr);
EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
EG(return_value_ptr_ptr) = &EX_T(opline->result.u.var).var.ptr;
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
zend_execute(EG(active_op_array) TSRMLS_CC);
@ -1999,13 +2005,13 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr)=original_return_value;
if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
zend_hash_destroy(EX(function_state).function_symbol_table);
FREE_HASHTABLE(EX(function_state).function_symbol_table);
zend_hash_destroy(function_symbol_table);
FREE_HASHTABLE(function_symbol_table);
} else {
/* clean before putting into the cache, since clean
could call dtors, which could use cached hash */
zend_hash_clean(EX(function_state).function_symbol_table);
*(++EG(symtable_cache_ptr)) = EX(function_state).function_symbol_table;
zend_hash_clean(function_symbol_table);
*(++EG(symtable_cache_ptr)) = function_symbol_table;
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
@ -2014,7 +2020,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
/* Not sure what should be done here if it's a static method */
if (EX(object)) {
Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC);
Z_OBJ_HT_P(EX(object))->call_method(EX(function_state).function->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
@ -2022,21 +2028,20 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
efree(EX(function_state).function->common.function_name);
}
efree(EX(fbc));
efree(EX(function_state).function);
if (!return_value_used) {
zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
} else {
EX_T(opline->result.u.var).var.ptr->is_ref = 0;
EX_T(opline->result.u.var).var.ptr->refcount = 1;
EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
}
}
ctor_opline = (zend_op*)zend_ptr_stack_pop(&EG(arg_types_stack));
if (EG(This)) {
if (EG(exception) && ctor_opline) {
if (RETURN_VALUE_USED(ctor_opline)) {
if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) {
if (IS_CTOR_USED(EX(called_scope))) {
EG(This)->refcount--;
}
if (EG(This)->refcount == 1) {
@ -2048,11 +2053,14 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
}
}
EX(object) = ex_object;
EX(called_scope) = DECODE_CTOR(EX(called_scope));
if (should_change_scope) {
EG(This) = current_this;
EG(scope) = current_scope;
EG(called_scope) = current_called_scope;
}
zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
EX(function_state).function = (zend_function *) EX(op_array);
EG(function_state_ptr) = &EX(function_state);
@ -2080,7 +2088,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
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_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
@ -2548,11 +2556,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_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline)));
/* We are not handling overloaded classes right now */
EX(object) = object_zval;
EX(fbc) = constructor;
EX(called_scope) = EX_T(opline->op1.u.var).class_entry;
ZEND_VM_NEXT_OPCODE();
}
@ -3832,14 +3841,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
while (EX(fbc)) {
zend_op *ctor_opline = (zend_op*)zend_ptr_stack_pop(&EG(arg_types_stack));
EX(called_scope) = (zend_class_entry*)zend_ptr_stack_pop(&EG(arg_types_stack));
if (EX(object)) {
if (ctor_opline && RETURN_VALUE_USED(ctor_opline)) {
if (IS_CTOR_USED(EX(called_scope))) {
EX(object)->refcount--;
}
zval_ptr_dtor(&EX(object));
}
EX(called_scope) = DECODE_CTOR(EX(called_scope));
zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
}

View File

@ -42,6 +42,7 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
/* Initialize execute_data */
EX(fbc) = NULL;
EX(called_scope) = NULL;
EX(object) = NULL;
EX(old_error_reporting) = NULL;
if (op_array->T < TEMP_VAR_STACK_LIMIT) {
@ -75,12 +76,6 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
EX(function_state).function = (zend_function *) op_array;
EG(function_state_ptr) = &EX(function_state);
#if ZEND_DEBUG
/* function_state.function_symbol_table is saved as-is to a stack,
* which is an intentional UMR. Shut it up if we're in DEBUG.
*/
EX(function_state).function_symbol_table = NULL;
#endif
while (1) {
#ifdef ZEND_WIN32
@ -126,11 +121,12 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
zval **original_return_value;
zend_class_entry *current_scope = NULL;
zval *current_this = NULL;
zend_class_entry *current_scope;
zend_class_entry *current_called_scope;
zval *current_this;
int return_value_used = RETURN_VALUE_USED(opline);
zend_bool should_change_scope;
zend_op *ctor_opline;
zval *ex_object;
if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
@ -144,41 +140,39 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EX(function_state).function->common.function_name);
}
}
if (EX(function_state).function->common.scope &&
!(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) &&
!EX(object)) {
zend_ptr_stack_2_push(&EG(argument_stack), (void *)(zend_uintptr_t)opline->extended_value, NULL);
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
} else {
/* FIXME: output identifiers properly */
zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
}
}
EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
if (EX(function_state).function->type == ZEND_USER_FUNCTION
|| EX(function_state).function->common.scope) {
if (EX(function_state).function->type == ZEND_USER_FUNCTION ||
EX(function_state).function->common.scope) {
should_change_scope = 1;
current_this = EG(This);
EG(This) = EX(object);
current_scope = EG(scope);
current_called_scope = EG(called_scope);
EG(This) = EX(object);
EG(scope) = (EX(function_state).function->type == ZEND_USER_FUNCTION || !EX(object)) ? EX(function_state).function->common.scope : NULL;
EG(called_scope) = EX(called_scope);
} else {
should_change_scope = 0;
}
EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
zend_ptr_stack_3_pop(&EG(arg_types_stack), (void*)&EX(called_scope), (void**)&ex_object, (void**)&EX(fbc));
zend_ptr_stack_2_push(&EG(argument_stack), (void *)(zend_uintptr_t)opline->extended_value, NULL);
EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr;
// EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
if (EX(function_state).function->common.scope) {
if (!EG(This) && !(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
int severity;
char *severity_word;
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
severity = E_STRICT;
severity_word = "should not";
} else {
severity = E_ERROR;
severity_word = "cannot";
}
zend_error(severity, "Non-static method %s::%s() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
}
}
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
unsigned char return_reference = EX(function_state).function->common.return_reference;
ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
INIT_ZVAL(*(EX_T(opline->result.u.var).var.ptr));
@ -214,21 +208,23 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
if (!return_value_used) {
zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
} else {
EX_T(opline->result.u.var).var.fcall_returned_reference = return_reference;
EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference;
}
} else if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
HashTable *function_symbol_table;
EX_T(opline->result.u.var).var.ptr = NULL;
if (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
/*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/
EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--);
function_symbol_table = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EX(function_state).function_symbol_table);
zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
ALLOC_HASHTABLE(function_symbol_table);
zend_hash_init(function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
/*printf("Cache miss! Initialized %x\n", function_symbol_table);*/
}
EG(active_symbol_table) = EX(function_state).function_symbol_table;
EG(active_symbol_table) = function_symbol_table;
original_return_value = EG(return_value_ptr_ptr);
EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
EG(return_value_ptr_ptr) = &EX_T(opline->result.u.var).var.ptr;
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
zend_execute(EG(active_op_array) TSRMLS_CC);
@ -247,13 +243,13 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EG(active_op_array) = EX(op_array);
EG(return_value_ptr_ptr)=original_return_value;
if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) {
zend_hash_destroy(EX(function_state).function_symbol_table);
FREE_HASHTABLE(EX(function_state).function_symbol_table);
zend_hash_destroy(function_symbol_table);
FREE_HASHTABLE(function_symbol_table);
} else {
/* clean before putting into the cache, since clean
could call dtors, which could use cached hash */
zend_hash_clean(EX(function_state).function_symbol_table);
*(++EG(symtable_cache_ptr)) = EX(function_state).function_symbol_table;
zend_hash_clean(function_symbol_table);
*(++EG(symtable_cache_ptr)) = function_symbol_table;
}
EG(active_symbol_table) = EX(symbol_table);
} else { /* ZEND_OVERLOADED_FUNCTION */
@ -262,7 +258,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
/* Not sure what should be done here if it's a static method */
if (EX(object)) {
Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC);
Z_OBJ_HT_P(EX(object))->call_method(EX(function_state).function->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC);
} else {
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
}
@ -270,21 +266,20 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
efree(EX(function_state).function->common.function_name);
}
efree(EX(fbc));
efree(EX(function_state).function);
if (!return_value_used) {
zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
} else {
EX_T(opline->result.u.var).var.ptr->is_ref = 0;
EX_T(opline->result.u.var).var.ptr->refcount = 1;
EX_T(opline->result.u.var).var.fcall_returned_reference = 0;
}
}
ctor_opline = (zend_op*)zend_ptr_stack_pop(&EG(arg_types_stack));
if (EG(This)) {
if (EG(exception) && ctor_opline) {
if (RETURN_VALUE_USED(ctor_opline)) {
if (EG(exception) && IS_CTOR_CALL(EX(called_scope))) {
if (IS_CTOR_USED(EX(called_scope))) {
EG(This)->refcount--;
}
if (EG(This)->refcount == 1) {
@ -296,11 +291,14 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
}
}
EX(object) = ex_object;
EX(called_scope) = DECODE_CTOR(EX(called_scope));
if (should_change_scope) {
EG(This) = current_this;
EG(scope) = current_scope;
EG(called_scope) = current_called_scope;
}
zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
EX(function_state).function = (zend_function *) EX(op_array);
EG(function_state_ptr) = &EX(function_state);
@ -421,11 +419,12 @@ static int ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
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_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline)));
/* We are not handling overloaded classes right now */
EX(object) = object_zval;
EX(fbc) = constructor;
EX(called_scope) = EX_T(opline->op1.u.var).class_entry;
ZEND_VM_NEXT_OPCODE();
}
@ -554,14 +553,14 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
while (EX(fbc)) {
zend_op *ctor_opline = (zend_op*)zend_ptr_stack_pop(&EG(arg_types_stack));
EX(called_scope) = (zend_class_entry*)zend_ptr_stack_pop(&EG(arg_types_stack));
if (EX(object)) {
if (ctor_opline && RETURN_VALUE_USED(ctor_opline)) {
if (IS_CTOR_USED(EX(called_scope))) {
EX(object)->refcount--;
}
zval_ptr_dtor(&EX(object));
}
EX(called_scope) = DECODE_CTOR(EX(called_scope));
zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
}
@ -665,7 +664,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST) {
function_name_strval = opline->op2.u.constant.value.str.val;
@ -824,7 +823,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_TMP_VAR == IS_CONST) {
function_name_strval = opline->op2.u.constant.value.str.val;
@ -940,7 +939,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST) {
function_name_strval = opline->op2.u.constant.value.str.val;
@ -1084,7 +1083,7 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CV == IS_CONST) {
function_name_strval = opline->op2.u.constant.value.str.val;
@ -1427,7 +1426,7 @@ static int ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *fname = &opline->op1.u.constant;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", fname->value.str.val);
@ -2392,7 +2391,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HAN
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST && IS_CONST == IS_CONST) {
/* try a function in namespace */
@ -2448,6 +2447,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HAN
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -2462,6 +2463,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HAN
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -2933,7 +2935,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST && IS_TMP_VAR == IS_CONST) {
/* try a function in namespace */
@ -2989,6 +2991,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -3003,6 +3007,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -3374,7 +3379,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST && IS_VAR == IS_CONST) {
/* try a function in namespace */
@ -3430,6 +3435,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -3444,6 +3451,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -3581,7 +3589,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HA
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST) {
/* try a function in namespace */
@ -3637,6 +3645,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HA
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -3651,6 +3661,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HA
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -3990,7 +4001,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_CONST == IS_CONST && IS_CV == IS_CONST) {
/* try a function in namespace */
@ -4046,6 +4057,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -4060,6 +4073,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -5473,7 +5487,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
int function_name_strlen;
zend_free_op free_op1;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = &opline->op2.u.constant;
@ -5500,6 +5514,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -5916,7 +5932,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op1, free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -5943,6 +5959,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -6361,7 +6379,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op1, free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -6388,6 +6406,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -6898,7 +6918,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op1;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
@ -6925,6 +6945,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -9503,7 +9525,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
int function_name_strlen;
zend_free_op free_op1;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = &opline->op2.u.constant;
@ -9530,6 +9552,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -9555,7 +9579,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST && IS_CONST == IS_CONST) {
/* try a function in namespace */
@ -9611,6 +9635,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -9625,6 +9651,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -11138,7 +11165,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op1, free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -11165,6 +11192,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -11191,7 +11220,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST && IS_TMP_VAR == IS_CONST) {
/* try a function in namespace */
@ -11247,6 +11276,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -11261,6 +11292,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -12746,7 +12778,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op1, free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -12773,6 +12805,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -12799,7 +12833,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST && IS_VAR == IS_CONST) {
/* try a function in namespace */
@ -12855,6 +12889,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -12869,6 +12905,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -13610,7 +13647,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST) {
/* try a function in namespace */
@ -13666,6 +13703,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -13680,6 +13719,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -14867,7 +14907,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op1;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
@ -14894,6 +14934,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -14919,7 +14961,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_
zval *function_name;
zend_class_entry *ce;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
if (IS_VAR == IS_CONST && IS_CV == IS_CONST) {
/* try a function in namespace */
@ -14975,6 +15017,8 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_
EX(fbc) = ce->constructor;
}
EX(called_scope) = ce;
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -14989,6 +15033,7 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_
}
if ((EX(object) = EG(This))) {
EX(object)->refcount++;
EX(called_scope) = Z_OBJCE_P(EX(object));
}
}
@ -16107,7 +16152,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
int function_name_strlen;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = &opline->op2.u.constant;
@ -16134,6 +16179,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -17137,7 +17184,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -17164,6 +17211,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -18101,7 +18150,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -18128,6 +18177,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -19330,7 +19381,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
int function_name_strlen;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
@ -19357,6 +19408,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -21914,7 +21967,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = &opline->op2.u.constant;
@ -21941,6 +21994,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -23392,7 +23447,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -23419,6 +23474,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -24909,7 +24966,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
@ -24936,6 +24993,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {
@ -26856,7 +26915,7 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
int function_name_strlen;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), NULL);
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
@ -26883,6 +26942,8 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
EX(called_scope) = Z_OBJCE_P(EX(object));
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
} else {

View File

@ -13,6 +13,7 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)
/* Initialize execute_data */
EX(fbc) = NULL;
EX(called_scope) = NULL;
EX(object) = NULL;
EX(old_error_reporting) = NULL;
if (op_array->T < TEMP_VAR_STACK_LIMIT) {
@ -46,12 +47,6 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)
EX(function_state).function = (zend_function *) op_array;
EG(function_state_ptr) = &EX(function_state);
#if ZEND_DEBUG
/* function_state.function_symbol_table is saved as-is to a stack,
* which is an intentional UMR. Shut it up if we're in DEBUG.
*/
EX(function_state).function_symbol_table = NULL;
#endif
while (1) {
{%ZEND_VM_CONTINUE_LABEL%}