mirror of
https://github.com/php/php-src.git
synced 2024-11-27 03:44:07 +08:00
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.
This commit is contained in:
parent
801768f72c
commit
49cf7c5d12
@ -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) &&
|
||||
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 = Z_OBJ(EG(current_execute_data)->This);
|
||||
fcc->called_scope = Z_OBJCE(EG(current_execute_data)->This);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)) {
|
||||
|
@ -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))) {
|
||||
} else {
|
||||
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 = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
|
||||
fcic.called_scope = called_scope;
|
||||
}
|
||||
}
|
||||
fcic.object = object ? Z_OBJ_P(object) : NULL;
|
||||
result = zend_call_function(&fci, &fcic);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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, ¶ms) == 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) {
|
||||
|
Loading…
Reference in New Issue
Block a user