mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Refactoring: use call_frames instead of call_slots
This commit is contained in:
parent
ba45650d63
commit
43477bc7a2
23 changed files with 1701 additions and 1762 deletions
|
@ -393,17 +393,24 @@ void shutdown_executor(TSRMLS_D) /* {{{ */
|
|||
/* return class name and "::" or "". */
|
||||
ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
|
||||
if (!zend_is_executing(TSRMLS_C)) {
|
||||
if (space) {
|
||||
*space = "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
switch (EG(current_execute_data)->function_state.function->type) {
|
||||
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
||||
func = EG(current_execute_data)->call->func;
|
||||
} else {
|
||||
func = (zend_function*)EG(current_execute_data)->op_array;
|
||||
}
|
||||
switch (func->type) {
|
||||
case ZEND_USER_FUNCTION:
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
{
|
||||
zend_class_entry *ce = EG(current_execute_data)->function_state.function->common.scope;
|
||||
zend_class_entry *ce = func->common.scope;
|
||||
|
||||
if (space) {
|
||||
*space = ce ? "::" : "";
|
||||
|
@ -421,12 +428,19 @@ ZEND_API const char *get_active_class_name(const char **space TSRMLS_DC) /* {{{
|
|||
|
||||
ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
||||
{
|
||||
zend_function *func;
|
||||
|
||||
if (!zend_is_executing(TSRMLS_C)) {
|
||||
return NULL;
|
||||
}
|
||||
switch (EG(current_execute_data)->function_state.function->type) {
|
||||
if (EG(current_execute_data)->call && (EG(current_execute_data)->call->flags & ZEND_CALL_DONE)) {
|
||||
func = EG(current_execute_data)->call->func;
|
||||
} else {
|
||||
func = (zend_function*)EG(current_execute_data)->op_array;
|
||||
}
|
||||
switch (func->type) {
|
||||
case ZEND_USER_FUNCTION: {
|
||||
zend_string *function_name = ((zend_op_array *) EG(current_execute_data)->function_state.function)->function_name;
|
||||
zend_string *function_name = func->common.function_name;
|
||||
|
||||
if (function_name) {
|
||||
return function_name->val;
|
||||
|
@ -436,7 +450,7 @@ ZEND_API const char *get_active_function_name(TSRMLS_D) /* {{{ */
|
|||
}
|
||||
break;
|
||||
case ZEND_INTERNAL_FUNCTION:
|
||||
return ((zend_internal_function *) EG(current_execute_data)->function_state.function)->function_name->val;
|
||||
return func->common.function_name->val;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
|
@ -655,6 +669,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
zend_class_entry *called_scope = NULL;
|
||||
zend_execute_data execute_data;
|
||||
zend_fcall_info_cache fci_cache_local;
|
||||
zend_function *func;
|
||||
zval tmp;
|
||||
|
||||
ZVAL_UNDEF(fci->retval);
|
||||
|
@ -719,7 +734,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
STR_RELEASE(callable_name);
|
||||
}
|
||||
|
||||
EX(function_state).function = fci_cache->function_handler;
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(ZEND_CALL_FRAME_SLOT + fci->param_count);
|
||||
|
||||
func = fci_cache->function_handler;
|
||||
EX(call) = zend_vm_stack_push_call_frame(func, fci->param_count, ZEND_CALL_DONE, fci_cache->called_scope, fci_cache->object, NULL TSRMLS_CC);
|
||||
calling_scope = fci_cache->calling_scope;
|
||||
called_scope = fci_cache->called_scope;
|
||||
fci->object = fci_cache->object;
|
||||
|
@ -729,24 +747,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
return FAILURE;
|
||||
}
|
||||
|
||||
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) {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name->val, EX(function_state).function->common.function_name->val);
|
||||
if (func->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) {
|
||||
if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", func->common.scope->name->val, func->common.function_name->val);
|
||||
}
|
||||
if (EX(function_state).function->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
|
||||
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
||||
EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
|
||||
EX(function_state).function->common.scope ? "::" : "",
|
||||
EX(function_state).function->common.function_name->val);
|
||||
func->common.scope ? func->common.scope->name->val : "",
|
||||
func->common.scope ? "::" : "",
|
||||
func->common.function_name->val);
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_VM_STACK_GROW_IF_NEEDED(fci->param_count + 1);
|
||||
|
||||
for (i=0; i<fci->param_count; i++) {
|
||||
zval *param;
|
||||
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
|
||||
if (ARG_SHOULD_BE_SENT_BY_REF(func, i + 1)) {
|
||||
// TODO: Scalar values don't have reference counters anymore.
|
||||
// They are assumed to be 1, and they may be easily passed by
|
||||
// reference now. However, previously scalars with refcount==1
|
||||
|
@ -766,19 +782,19 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
(!Z_ISREF(fci->params[i]) && Z_REFCOUNT(fci->params[i]) > 1)) {
|
||||
|
||||
if (fci->no_separation &&
|
||||
!ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) {
|
||||
!ARG_MAY_BE_SENT_BY_REF(func, i + 1)) {
|
||||
if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) {
|
||||
/* hack to clean up the stack */
|
||||
ZVAL_LONG(&tmp, i);
|
||||
zend_vm_stack_push(&tmp TSRMLS_CC);
|
||||
zend_vm_stack_clear_multiple(0 TSRMLS_CC);
|
||||
zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
||||
i+1,
|
||||
EX(function_state).function->common.scope ? EX(function_state).function->common.scope->name->val : "",
|
||||
EX(function_state).function->common.scope ? "::" : "",
|
||||
EX(function_state).function->common.function_name->val);
|
||||
func->common.scope ? func->common.scope->name->val : "",
|
||||
func->common.scope ? "::" : "",
|
||||
func->common.function_name->val);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
@ -797,7 +813,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
param = &fci->params[i];
|
||||
} else if (Z_ISREF(fci->params[i]) &&
|
||||
/* don't separate references for __call */
|
||||
(EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||
(func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0 ) {
|
||||
param = &tmp;
|
||||
ZVAL_DUP(param, Z_REFVAL(fci->params[i]));
|
||||
} else {
|
||||
|
@ -807,13 +823,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
zend_vm_stack_push(param TSRMLS_CC);
|
||||
}
|
||||
|
||||
EX(function_state).arguments = zend_vm_stack_top_inc(TSRMLS_C);
|
||||
ZVAL_LONG(EX(function_state).arguments, fci->param_count);
|
||||
|
||||
EG(scope) = calling_scope;
|
||||
EG(called_scope) = called_scope;
|
||||
if (!fci->object ||
|
||||
(EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
Z_OBJ(EG(This)) = NULL;
|
||||
} else {
|
||||
Z_OBJ(EG(This)) = fci->object;
|
||||
|
@ -823,9 +836,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
EX(prev_execute_data) = EG(current_execute_data);
|
||||
EG(current_execute_data) = &execute_data;
|
||||
|
||||
if (EX(function_state).function->type == ZEND_USER_FUNCTION) {
|
||||
if (func->type == ZEND_USER_FUNCTION) {
|
||||
calling_symbol_table = EG(active_symbol_table);
|
||||
EG(scope) = EX(function_state).function->common.scope;
|
||||
EG(scope) = func->common.scope;
|
||||
if (fci->symbol_table) {
|
||||
EG(active_symbol_table) = fci->symbol_table;
|
||||
} else {
|
||||
|
@ -833,7 +846,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
}
|
||||
|
||||
original_op_array = EG(active_op_array);
|
||||
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
|
||||
EG(active_op_array) = (zend_op_array *) func;
|
||||
original_opline_ptr = EG(opline_ptr);
|
||||
|
||||
if (EXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) == 0)) {
|
||||
|
@ -848,15 +861,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
|
||||
}
|
||||
EG(active_symbol_table) = calling_symbol_table;
|
||||
} else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
|
||||
int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
|
||||
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
|
||||
int call_via_handler = (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
|
||||
ZVAL_NULL(fci->retval);
|
||||
if (EX(function_state).function->common.scope) {
|
||||
EG(scope) = EX(function_state).function->common.scope;
|
||||
if (func->common.scope) {
|
||||
EG(scope) = func->common.scope;
|
||||
}
|
||||
if (EXPECTED(zend_execute_internal == NULL)) {
|
||||
/* saves one function call if zend_execute_internal is not used */
|
||||
EX(function_state).function->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
|
||||
func->internal_function.handler(fci->param_count, fci->retval TSRMLS_CC);
|
||||
} else {
|
||||
zend_execute_internal(&execute_data, fci TSRMLS_CC);
|
||||
}
|
||||
|
@ -880,22 +893,22 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
|||
|
||||
/* Not sure what should be done here if it's a static method */
|
||||
if (fci->object) {
|
||||
fci->object->handlers->call_method(EX(function_state).function->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
|
||||
fci->object->handlers->call_method(func->common.function_name, fci->object, fci->param_count, fci->retval TSRMLS_CC);
|
||||
} else {
|
||||
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
|
||||
}
|
||||
|
||||
if (EX(function_state).function->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||
STR_RELEASE(EX(function_state).function->common.function_name);
|
||||
if (func->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
||||
STR_RELEASE(func->common.function_name);
|
||||
}
|
||||
efree(EX(function_state).function);
|
||||
efree(func);
|
||||
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(fci->retval);
|
||||
ZVAL_UNDEF(fci->retval);
|
||||
}
|
||||
}
|
||||
zend_vm_stack_clear_multiple(0 TSRMLS_CC);
|
||||
zend_vm_stack_free_call_frame(EX(call), 0 TSRMLS_CC);
|
||||
|
||||
if (Z_OBJ(EG(This))) {
|
||||
zval_ptr_dtor(&EG(This));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue