mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Mark first call frames of stack segment with ZEND_CALL_ALLOCATED flag to simplify checks on stack deallocation.
This commit is contained in:
parent
653e8c58c8
commit
0586702d32
5 changed files with 55 additions and 51 deletions
|
@ -455,6 +455,7 @@ struct _zend_execute_data {
|
|||
#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4)
|
||||
#define ZEND_CALL_CLOSURE (1 << 5)
|
||||
#define ZEND_CALL_RELEASE_THIS (1 << 6)
|
||||
#define ZEND_CALL_ALLOCATED (1 << 7)
|
||||
|
||||
#define ZEND_CALL_INFO(call) \
|
||||
(Z_TYPE_INFO((call)->This) >> 24)
|
||||
|
|
|
@ -2077,7 +2077,7 @@ ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data
|
|||
EG(vm_stack_top) = EG(vm_stack)->top;
|
||||
EG(vm_stack_end) = EG(vm_stack)->end;
|
||||
|
||||
call_info = ZEND_CALL_TOP_FUNCTION | (ZEND_CALL_INFO(call) & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS));
|
||||
call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | (ZEND_CALL_INFO(call) & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS));
|
||||
if (Z_OBJ(call->This)) {
|
||||
call_info |= ZEND_CALL_RELEASE_THIS;
|
||||
}
|
||||
|
|
|
@ -153,24 +153,19 @@ ZEND_API void zend_vm_stack_init(void);
|
|||
ZEND_API void zend_vm_stack_destroy(void);
|
||||
ZEND_API void* zend_vm_stack_extend(size_t size);
|
||||
|
||||
static zend_always_inline zval* zend_vm_stack_alloc(size_t size)
|
||||
{
|
||||
char *top = (char*)EG(vm_stack_top);
|
||||
|
||||
if (UNEXPECTED(size > (size_t)(((char*)EG(vm_stack_end)) - top))) {
|
||||
return (zval*)zend_vm_stack_extend(size);
|
||||
}
|
||||
EG(vm_stack_top) = (zval*)(top + size);
|
||||
return (zval*)top;
|
||||
}
|
||||
|
||||
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
|
||||
{
|
||||
zend_execute_data *call = (zend_execute_data*)zend_vm_stack_alloc(used_stack);
|
||||
zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top);
|
||||
|
||||
if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) {
|
||||
call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
|
||||
ZEND_SET_CALL_INFO(call, call_info | ZEND_CALL_ALLOCATED);
|
||||
} else {
|
||||
EG(vm_stack_top) = (zval*)((char*)call + used_stack);
|
||||
ZEND_SET_CALL_INFO(call, call_info);
|
||||
}
|
||||
call->func = func;
|
||||
Z_OBJ(call->This) = object;
|
||||
ZEND_SET_CALL_INFO(call, call_info);
|
||||
ZEND_CALL_NUM_ARGS(call) = num_args;
|
||||
call->called_scope = called_scope;
|
||||
return call;
|
||||
|
@ -240,10 +235,11 @@ static zend_always_inline void zend_vm_stack_free_args(zend_execute_data *call)
|
|||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call)
|
||||
static zend_always_inline void zend_vm_stack_free_call_frame_ex(uint32_t call_info, zend_execute_data *call)
|
||||
{
|
||||
zend_vm_stack p = EG(vm_stack);
|
||||
if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(p) == (zval*)call)) {
|
||||
if (UNEXPECTED(call_info & ZEND_CALL_ALLOCATED)) {
|
||||
zend_vm_stack p = EG(vm_stack);
|
||||
|
||||
zend_vm_stack prev = p->prev;
|
||||
|
||||
EG(vm_stack_top) = prev->top;
|
||||
|
@ -255,6 +251,11 @@ static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *
|
|||
}
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_vm_stack_free_call_frame(zend_execute_data *call)
|
||||
{
|
||||
zend_vm_stack_free_call_frame_ex(ZEND_CALL_INFO(call), call);
|
||||
}
|
||||
|
||||
/* services */
|
||||
ZEND_API const char *get_active_class_name(const char **space);
|
||||
ZEND_API const char *get_active_function_name(void);
|
||||
|
|
|
@ -2395,7 +2395,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
|||
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
||||
zend_clean_and_cache_symbol_table(EX(symbol_table));
|
||||
}
|
||||
zend_vm_stack_free_extra_args(execute_data);
|
||||
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
|
||||
old_execute_data = execute_data;
|
||||
execute_data = EG(current_execute_data) = EX(prev_execute_data);
|
||||
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
|
||||
|
@ -2420,7 +2420,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
|||
}
|
||||
EG(scope) = EX(func)->op_array.scope;
|
||||
|
||||
zend_vm_stack_free_call_frame(old_execute_data);
|
||||
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
|
||||
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
const zend_op *old_opline = EX(opline);
|
||||
|
@ -2440,7 +2440,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
|||
efree_size(EX(func), sizeof(zend_op_array));
|
||||
old_execute_data = execute_data;
|
||||
execute_data = EG(current_execute_data) = EX(prev_execute_data);
|
||||
zend_vm_stack_free_call_frame(old_execute_data);
|
||||
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
|
||||
|
||||
zend_attach_symbol_table(execute_data);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
|
@ -2457,7 +2457,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
|||
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
||||
zend_clean_and_cache_symbol_table(EX(symbol_table));
|
||||
}
|
||||
zend_vm_stack_free_extra_args(execute_data);
|
||||
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
|
||||
EG(current_execute_data) = EX(prev_execute_data);
|
||||
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
|
||||
OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
|
||||
|
@ -2478,7 +2478,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
|
|||
}
|
||||
EG(current_execute_data) = EX(prev_execute_data);
|
||||
}
|
||||
zend_vm_stack_free_call_frame(execute_data);
|
||||
zend_vm_stack_free_call_frame_ex(call_info, execute_data);
|
||||
|
||||
ZEND_VM_RETURN();
|
||||
}
|
||||
|
|
|
@ -446,7 +446,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
|
|||
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
||||
zend_clean_and_cache_symbol_table(EX(symbol_table));
|
||||
}
|
||||
zend_vm_stack_free_extra_args(execute_data);
|
||||
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
|
||||
old_execute_data = execute_data;
|
||||
execute_data = EG(current_execute_data) = EX(prev_execute_data);
|
||||
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
|
||||
|
@ -471,7 +471,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
|
|||
}
|
||||
EG(scope) = EX(func)->op_array.scope;
|
||||
|
||||
zend_vm_stack_free_call_frame(old_execute_data);
|
||||
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
|
||||
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
const zend_op *old_opline = EX(opline);
|
||||
|
@ -491,7 +491,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
|
|||
efree_size(EX(func), sizeof(zend_op_array));
|
||||
old_execute_data = execute_data;
|
||||
execute_data = EG(current_execute_data) = EX(prev_execute_data);
|
||||
zend_vm_stack_free_call_frame(old_execute_data);
|
||||
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
|
||||
|
||||
zend_attach_symbol_table(execute_data);
|
||||
if (UNEXPECTED(EG(exception) != NULL)) {
|
||||
|
@ -508,7 +508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
|
|||
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
||||
zend_clean_and_cache_symbol_table(EX(symbol_table));
|
||||
}
|
||||
zend_vm_stack_free_extra_args(execute_data);
|
||||
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
|
||||
EG(current_execute_data) = EX(prev_execute_data);
|
||||
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
|
||||
OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
|
||||
|
@ -529,7 +529,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_
|
|||
}
|
||||
EG(current_execute_data) = EX(prev_execute_data);
|
||||
}
|
||||
zend_vm_stack_free_call_frame(execute_data);
|
||||
zend_vm_stack_free_call_frame_ex(call_info, execute_data);
|
||||
|
||||
ZEND_VM_RETURN();
|
||||
}
|
||||
|
@ -2058,7 +2058,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_H
|
|||
try_function_name:
|
||||
if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
|
||||
const char *colon;
|
||||
|
||||
|
||||
if ((colon = zend_memrchr(Z_STRVAL_P(function_name), ':', Z_STRLEN_P(function_name))) != NULL &&
|
||||
colon > Z_STRVAL_P(function_name) &&
|
||||
*(colon-1) == ':'
|
||||
|
@ -2066,24 +2066,24 @@ try_function_name:
|
|||
zend_string *mname;
|
||||
size_t cname_length = colon - Z_STRVAL_P(function_name) - 1;
|
||||
size_t mname_length = Z_STRLEN_P(function_name) - cname_length - (sizeof("::") - 1);
|
||||
|
||||
|
||||
if (!mname_length) {
|
||||
zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
lcname = zend_string_init(Z_STRVAL_P(function_name), cname_length, 0);
|
||||
|
||||
|
||||
called_scope = zend_fetch_class_by_name(lcname, NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(called_scope == NULL)) {
|
||||
zend_string_release(lcname);
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
|
||||
mname = zend_string_init(Z_STRVAL_P(function_name) + (cname_length + sizeof("::") - 1), mname_length, 0);
|
||||
|
||||
|
||||
if (called_scope->get_static_method) {
|
||||
fbc = called_scope->get_static_method(called_scope, mname);
|
||||
} else {
|
||||
|
@ -2098,10 +2098,10 @@ try_function_name:
|
|||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
zend_string_release(lcname);
|
||||
zend_string_release(mname);
|
||||
|
||||
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
zend_error(E_DEPRECATED,
|
||||
|
@ -2135,6 +2135,7 @@ try_function_name:
|
|||
called_scope = NULL;
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
} else if (IS_CONST != IS_CONST &&
|
||||
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
|
||||
Z_OBJ_HANDLER_P(function_name, get_closure) &&
|
||||
|
@ -2529,7 +2530,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HAND
|
|||
try_function_name:
|
||||
if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
|
||||
const char *colon;
|
||||
|
||||
|
||||
if ((colon = zend_memrchr(Z_STRVAL_P(function_name), ':', Z_STRLEN_P(function_name))) != NULL &&
|
||||
colon > Z_STRVAL_P(function_name) &&
|
||||
*(colon-1) == ':'
|
||||
|
@ -2537,24 +2538,24 @@ try_function_name:
|
|||
zend_string *mname;
|
||||
size_t cname_length = colon - Z_STRVAL_P(function_name) - 1;
|
||||
size_t mname_length = Z_STRLEN_P(function_name) - cname_length - (sizeof("::") - 1);
|
||||
|
||||
|
||||
if (!mname_length) {
|
||||
zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
|
||||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
lcname = zend_string_init(Z_STRVAL_P(function_name), cname_length, 0);
|
||||
|
||||
|
||||
called_scope = zend_fetch_class_by_name(lcname, NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(called_scope == NULL)) {
|
||||
zend_string_release(lcname);
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
|
||||
mname = zend_string_init(Z_STRVAL_P(function_name) + (cname_length + sizeof("::") - 1), mname_length, 0);
|
||||
|
||||
|
||||
if (called_scope->get_static_method) {
|
||||
fbc = called_scope->get_static_method(called_scope, mname);
|
||||
} else {
|
||||
|
@ -2569,10 +2570,10 @@ try_function_name:
|
|||
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
zend_string_release(lcname);
|
||||
zend_string_release(mname);
|
||||
|
||||
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
zend_error(E_DEPRECATED,
|
||||
|
@ -2606,6 +2607,7 @@ try_function_name:
|
|||
called_scope = NULL;
|
||||
object = NULL;
|
||||
}
|
||||
|
||||
} else if (IS_CV != IS_CONST &&
|
||||
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
|
||||
Z_OBJ_HANDLER_P(function_name, get_closure) &&
|
||||
|
@ -2781,7 +2783,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_
|
|||
try_function_name:
|
||||
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
|
||||
const char *colon;
|
||||
|
||||
|
||||
if ((colon = zend_memrchr(Z_STRVAL_P(function_name), ':', Z_STRLEN_P(function_name))) != NULL &&
|
||||
colon > Z_STRVAL_P(function_name) &&
|
||||
*(colon-1) == ':'
|
||||
|
@ -2789,24 +2791,24 @@ try_function_name:
|
|||
zend_string *mname;
|
||||
size_t cname_length = colon - Z_STRVAL_P(function_name) - 1;
|
||||
size_t mname_length = Z_STRLEN_P(function_name) - cname_length - (sizeof("::") - 1);
|
||||
|
||||
|
||||
if (!mname_length) {
|
||||
zend_error(E_EXCEPTION | E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
|
||||
zval_ptr_dtor_nogc(free_op2);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
lcname = zend_string_init(Z_STRVAL_P(function_name), cname_length, 0);
|
||||
|
||||
|
||||
called_scope = zend_fetch_class_by_name(lcname, NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
|
||||
if (UNEXPECTED(called_scope == NULL)) {
|
||||
zend_string_release(lcname);
|
||||
CHECK_EXCEPTION();
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
|
||||
mname = zend_string_init(Z_STRVAL_P(function_name) + (cname_length + sizeof("::") - 1), mname_length, 0);
|
||||
|
||||
|
||||
if (called_scope->get_static_method) {
|
||||
fbc = called_scope->get_static_method(called_scope, mname);
|
||||
} else {
|
||||
|
@ -2821,10 +2823,10 @@ try_function_name:
|
|||
zval_ptr_dtor_nogc(free_op2);
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
zend_string_release(lcname);
|
||||
zend_string_release(mname);
|
||||
|
||||
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
zend_error(E_DEPRECATED,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue