本文支援建立最簡單的物件
static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
{
//根據引數和方法,計算使用的堆疊
uint32_t used_stack = zend_vm_calc_used_stack(num_args, func);
return zend_vm_stack_push_call_frame_ex(used_stack, call_info,
func, num_args, called_scope, object);
}
1.zend_vm_calc_used_stack
static zend_always_inline uint32_t zend_vm_calc_used_stack(uint32_t num_args, zend_function *func)
{
//槽,加上引數數量個數
uint32_t used_stack = ZEND_CALL_FRAME_SLOT + num_args;
//ZEND_USER_CODE(type) ((type & 1) == 0)
if (EXPECTED(ZEND_USER_CODE(func->type))) {
//加上op_array最後一個定義的變數,加上臨時變數和返回值的大小,減去一個重複的變數個數
used_stack += func->op_array.last_var + func->op_array.T - MIN(func->op_array.num_args, num_args);
}
return used_stack * sizeof(zval);
}
//兩個結構體的長度除以一個zval的長度,得出佔用幾個zval的個數,aligned 對其方式
#define ZEND_CALL_FRAME_SLOT \
((int)((ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / ZEND_MM_ALIGNED_SIZE(sizeof(zval))))
2.zend_vm_stack_push_call_frame_ex
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*)EG(vm_stack_top);
ZEND_ASSERT_VM_STACK_GLOBAL;
//需要的堆疊空間大於剩餘可用的,則擴容
if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) {
call = (zend_execute_data*)zend_vm_stack_extend(used_stack);
ZEND_ASSERT_VM_STACK_GLOBAL;
//call_info ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR
// func constructor
zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, called_scope, object);
return call;
} else {
EG(vm_stack_top) = (zval*)((char*)call + used_stack);
zend_vm_init_call_frame(call, call_info, func, num_args, called_scope, object);
return call;
}
}
ZEND_API void* zend_vm_stack_extend(size_t size)
{
zend_vm_stack stack;
void *ptr;
stack = EG(vm_stack);
stack->top = EG(vm_stack_top);
EG(vm_stack) = stack = zend_vm_stack_new_page(
EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE(0)) ?
ZEND_VM_STACK_PAGE_SIZE(0) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(0, size),
stack);
ptr = stack->top;
EG(vm_stack_top) = (void*)(((char*)ptr) + size);
EG(vm_stack_end) = stack->end;
return ptr;
}
static zend_always_inline void zend_vm_init_call_frame(zend_execute_data *call, uint32_t call_info, zend_function *func, uint32_t num_args, zend_class_entry *called_scope, zend_object *object)
{
call->func = func;
if (object) {
//#define Z_OBJ(zval) (zval).value.obj,this值
Z_OBJ(call->This) = object;
ZEND_SET_CALL_INFO(call, 1, call_info);
} else {
Z_CE(call->This) = called_scope;
//#define ZEND_SET_CALL_INFO(call, object, info) do { \
//Z_TYPE_INFO((call)->This) = ((object) ? IS_OBJECT_EX : IS_UNDEF) | ((info) << //ZEND_CALL_INFO_SHIFT); \
//} while (0)
ZEND_SET_CALL_INFO(call, 0, call_info);
}
//#define ZEND_CALL_NUM_ARGS(call) \
// (call)->This.u2.num_args
ZEND_CALL_NUM_ARGS(call) = num_args;
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結