summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2015-04-23 12:16:37 +0300
committerDmitry Stogov <dmitry@zend.com>2015-04-23 12:16:37 +0300
commit49cf7c5d120876b52fb187e4c13f4adc4fc4d9a6 (patch)
tree98dd1e2611a86e363a9c8f35f91a033eb5c1d0e6
parent801768f72ceb5682b3bc6c10827f747d93753a58 (diff)
downloadphp-git-49cf7c5d120876b52fb187e4c13f4adc4fc4d9a6.tar.gz
Don't propogate "fake" EX(called_scope) and EX(This) into each internal function.
They need quite seldom and it's cheaper to get them from corresponfing upper stack frame.
-rw-r--r--Zend/zend_API.c49
-rw-r--r--Zend/zend_builtin_functions.c19
-rw-r--r--Zend/zend_constants.c5
-rw-r--r--Zend/zend_execute.h2
-rw-r--r--Zend/zend_execute_API.c37
-rw-r--r--Zend/zend_interfaces.c15
-rw-r--r--Zend/zend_object_handlers.c7
-rw-r--r--Zend/zend_vm_def.h9
-rw-r--r--Zend/zend_vm_execute.h11
-rw-r--r--Zend/zend_vm_execute.skl2
-rw-r--r--ext/standard/basic_functions.c16
11 files changed, 99 insertions, 73 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index dc51713807..f028756a93 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -2864,10 +2864,10 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
if (!EG(scope)) {
if (error) *error = estrdup("cannot access self:: when no class scope is active");
} else {
- fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
+ fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
fcc->calling_scope = EG(scope);
- if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) {
- fcc->object = Z_OBJ(EG(current_execute_data)->This);
+ if (!fcc->object) {
+ fcc->object = zend_get_this_object(EG(current_execute_data));
}
ret = 1;
}
@@ -2877,22 +2877,24 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
} else if (!EG(scope)->parent) {
if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
} else {
- fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
+ fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
fcc->calling_scope = EG(scope)->parent;
- if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) {
- fcc->object = Z_OBJ(EG(current_execute_data)->This);
+ if (!fcc->object) {
+ fcc->object = zend_get_this_object(EG(current_execute_data));
}
*strict_class = 1;
ret = 1;
}
} else if (zend_string_equals_literal(lcname, "static")) {
- if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) {
+ zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
+
+ if (!called_scope) {
if (error) *error = estrdup("cannot access static:: when no class scope is active");
} else {
- fcc->called_scope = EG(current_execute_data)->called_scope;
- fcc->calling_scope = EG(current_execute_data)->called_scope;
- if (!fcc->object && Z_OBJ(EG(current_execute_data)->This)) {
- fcc->object = Z_OBJ(EG(current_execute_data)->This);
+ fcc->called_scope = called_scope;
+ fcc->calling_scope = called_scope;
+ if (!fcc->object) {
+ fcc->object = zend_get_this_object(EG(current_execute_data));
}
*strict_class = 1;
ret = 1;
@@ -2906,11 +2908,17 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
}
scope = ex ? ex->func->common.scope : NULL;
fcc->calling_scope = ce;
- if (scope && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
- instanceof_function(Z_OBJCE(EG(current_execute_data)->This), scope) &&
- instanceof_function(scope, fcc->calling_scope)) {
- fcc->object = Z_OBJ(EG(current_execute_data)->This);
- fcc->called_scope = Z_OBJCE(EG(current_execute_data)->This);
+ if (scope && !fcc->object) {
+ zend_object *object = zend_get_this_object(EG(current_execute_data));
+
+ if (object &&
+ instanceof_function(object->ce, scope) &&
+ instanceof_function(scope, fcc->calling_scope)) {
+ fcc->object = object;
+ fcc->called_scope = object->ce;
+ } else {
+ fcc->called_scope = fcc->calling_scope;
+ }
} else {
fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
}
@@ -3101,9 +3109,12 @@ get_function_via_handler:
if (fcc->function_handler) {
retval = 1;
call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
- if (call_via_handler && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
- instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope)) {
- fcc->object = Z_OBJ(EG(current_execute_data)->This);
+ if (call_via_handler && !fcc->object) {
+ zend_object *object = zend_get_this_object(EG(current_execute_data));
+ if (object &&
+ instanceof_function(object->ce, fcc->calling_scope)) {
+ fcc->object = object;
+ }
}
}
}
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 996c11b24d..7313b32065 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -916,12 +916,15 @@ ZEND_FUNCTION(get_class)
Retrieves the "Late Static Binding" class name */
ZEND_FUNCTION(get_called_class)
{
+ zend_class_entry *called_scope;
+
if (zend_parse_parameters_none() == FAILURE) {
return;
}
- if (EX(called_scope)) {
- RETURN_STR_COPY(EX(called_scope)->name);
+ called_scope = zend_get_called_scope(execute_data);
+ if (called_scope) {
+ RETURN_STR_COPY(called_scope->name);
} else if (!EG(scope)) {
zend_error(E_WARNING, "get_called_class() called from outside a class");
}
@@ -2304,12 +2307,6 @@ ZEND_FUNCTION(debug_print_backtrace)
/* $this may be passed into regular internal functions */
object = Z_OBJ(call->This);
- if (object &&
- call &&
- call->func->type == ZEND_INTERNAL_FUNCTION &&
- !call->func->common.scope) {
- object = NULL;
- }
if (call->func) {
func = call->func;
@@ -2527,12 +2524,6 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
/* $this may be passed into regular internal functions */
object = call ? Z_OBJ(call->This) : NULL;
- if (object &&
- call->func &&
- call->func->type == ZEND_INTERNAL_FUNCTION &&
- !call->func->common.scope) {
- object = NULL;
- }
if (call && call->func) {
func = call->func;
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 32f249ce08..f8205fac0d 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -349,12 +349,11 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
}
} else if (class_name_len == sizeof("static")-1 &&
!memcmp(lcname, "static", sizeof("static")-1)) {
- if (UNEXPECTED(!EG(current_execute_data)) ||
- UNEXPECTED(!EG(current_execute_data)->called_scope)) {
+ ce = zend_get_called_scope(EG(current_execute_data));
+ if (UNEXPECTED(!ce)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot access static:: when no class scope is active");
return NULL;
}
- ce = EG(current_execute_data)->called_scope;
} else {
ce = zend_fetch_class(class_name, flags);
}
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index 67958cf32c..9e8dde5c3c 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -42,6 +42,8 @@ ZEND_API void execute_ex(zend_execute_data *execute_data);
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value);
ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);
ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload);
+ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex);
+ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name);
ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name);
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions);
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 37a27150e5..61ee1e103e 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -1055,6 +1055,38 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
}
/* }}} */
+ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
+{
+ while (ex) {
+ if (ex->called_scope) {
+ return ex->called_scope;
+ } else if (ex->func) {
+ if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
+ return ex->called_scope;
+ }
+ }
+ ex = ex->prev_execute_data;
+ }
+ return NULL;
+}
+/* }}} */
+
+ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
+{
+ while (ex) {
+ if (Z_OBJ(ex->This)) {
+ return Z_OBJ(ex->This);
+ } else if (ex->func) {
+ if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
+ return Z_OBJ(ex->This);
+ }
+ }
+ ex = ex->prev_execute_data;
+ }
+ return NULL;
+}
+/* }}} */
+
ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */
{
zval pv;
@@ -1311,13 +1343,14 @@ check_fetch_type:
}
return EG(scope)->parent;
case ZEND_FETCH_CLASS_STATIC:
- if (UNEXPECTED(!EG(current_execute_data)) || UNEXPECTED(!EG(current_execute_data)->called_scope)) {
+ ce = zend_get_called_scope(EG(current_execute_data));
+ if (UNEXPECTED(!ce)) {
int error_type = (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) ?
(E_EXCEPTION | E_ERROR) : E_ERROR;
zend_error(error_type, "Cannot access static:: when no class scope is active");
return NULL;
}
- return EG(current_execute_data)->called_scope;
+ return ce;
case ZEND_FETCH_CLASS_AUTO: {
fetch_sub_type = zend_get_class_fetch_type(class_name);
if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c
index 5cb7024706..54f8f8c117 100644
--- a/Zend/zend_interfaces.c
+++ b/Zend/zend_interfaces.c
@@ -89,13 +89,16 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun
fcic.calling_scope = obj_ce;
if (object) {
fcic.called_scope = Z_OBJCE_P(object);
- } else if (obj_ce &&
- !(EG(current_execute_data) &&
- EG(current_execute_data)->called_scope &&
- instanceof_function(EG(current_execute_data)->called_scope, obj_ce))) {
- fcic.called_scope = obj_ce;
} else {
- fcic.called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
+ zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
+
+ if (obj_ce &&
+ (!called_scope ||
+ !instanceof_function(called_scope, obj_ce))) {
+ fcic.called_scope = obj_ce;
+ } else {
+ fcic.called_scope = called_scope;
+ }
}
fcic.object = object ? Z_OBJ_P(object) : NULL;
result = zend_call_function(&fci, &fcic);
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index a14f60080b..52c3b4ce1c 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -1137,6 +1137,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
zend_function *fbc = NULL;
char *lc_class_name;
zend_string *lc_function_name;
+ zend_object *object;
if (EXPECTED(key != NULL)) {
lc_function_name = Z_STR_P(key);
@@ -1164,12 +1165,12 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
zend_string_release(lc_function_name);
}
if (ce->__call &&
- Z_OBJ(EG(current_execute_data)->This) &&
- instanceof_function(Z_OBJCE(EG(current_execute_data)->This), ce)) {
+ (object = zend_get_this_object(EG(current_execute_data))) != NULL &&
+ instanceof_function(object->ce, ce)) {
/* Call the top-level defined __call().
* see: tests/classes/__call_004.phpt */
- zend_class_entry *call_ce = Z_OBJCE(EG(current_execute_data)->This);
+ zend_class_entry *call_ce = object->ce;
while (!call_ce->__call) {
call_ce = call_ce->parent;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 9a50c9b7d5..899b18a89d 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3391,9 +3391,6 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY)
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
- call->called_scope = EX(called_scope);
- Z_OBJ(call->This) = Z_OBJ(EX(This));
-
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
@@ -3505,9 +3502,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
}
}
- call->called_scope = EX(called_scope);
- Z_OBJ(call->This) = Z_OBJ(EX(This));
-
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
@@ -3627,9 +3621,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
if (fbc->common.scope) {
should_change_scope = 1;
EG(scope) = fbc->common.scope;
- } else {
- call->called_scope = EX(called_scope);
- Z_OBJ(call->This) = Z_OBJ(EX(This));
}
call->prev_execute_data = execute_data;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 9f224ee0dd..3a2ed291eb 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -423,7 +423,7 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
}
execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE,
- (zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL);
+ (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
if (EG(current_execute_data)) {
execute_data->symbol_table = zend_rebuild_symbol_table();
} else {
@@ -548,9 +548,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
- call->called_scope = EX(called_scope);
- Z_OBJ(call->This) = Z_OBJ(EX(This));
-
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
@@ -662,9 +659,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(
}
}
- call->called_scope = EX(called_scope);
- Z_OBJ(call->This) = Z_OBJ(EX(This));
-
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
@@ -784,9 +778,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC
if (fbc->common.scope) {
should_change_scope = 1;
EG(scope) = fbc->common.scope;
- } else {
- call->called_scope = EX(called_scope);
- Z_OBJ(call->This) = Z_OBJ(EX(This));
}
call->prev_execute_data = execute_data;
diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl
index 5bbc390f5b..02fe6bdc36 100644
--- a/Zend/zend_vm_execute.skl
+++ b/Zend/zend_vm_execute.skl
@@ -29,7 +29,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value
}
execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE,
- (zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL);
+ (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
if (EG(current_execute_data)) {
execute_data->symbol_table = zend_rebuild_symbol_table();
} else {
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index ebeca422df..693ac4c8e3 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -4800,6 +4800,7 @@ PHP_FUNCTION(forward_static_call)
zval retval;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
+ zend_class_entry *called_scope;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &fci, &fci_cache, &fci.params, &fci.param_count) == FAILURE) {
return;
@@ -4811,9 +4812,10 @@ PHP_FUNCTION(forward_static_call)
fci.retval = &retval;
- if (EX(called_scope) &&
- instanceof_function(EX(called_scope), fci_cache.calling_scope)) {
- fci_cache.called_scope = EX(called_scope);
+ called_scope = zend_get_called_scope(execute_data);
+ if (called_scope &&
+ instanceof_function(called_scope, fci_cache.calling_scope)) {
+ fci_cache.called_scope = called_scope;
}
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
@@ -4829,6 +4831,7 @@ PHP_FUNCTION(forward_static_call_array)
zval *params, retval;
zend_fcall_info fci;
zend_fcall_info_cache fci_cache;
+ zend_class_entry *called_scope;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "fa/", &fci, &fci_cache, &params) == FAILURE) {
return;
@@ -4837,9 +4840,10 @@ PHP_FUNCTION(forward_static_call_array)
zend_fcall_info_args(&fci, params);
fci.retval = &retval;
- if (EX(called_scope) &&
- instanceof_function(EX(called_scope), fci_cache.calling_scope)) {
- fci_cache.called_scope = EX(called_scope);
+ called_scope = zend_get_called_scope(execute_data);
+ if (called_scope &&
+ instanceof_function(called_scope, fci_cache.calling_scope)) {
+ fci_cache.called_scope = called_scope;
}
if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {