zend_vm_stack_push_call_frame

本文支持创建最简单的对象

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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!