文档章节

function参数

o
 osc_y8yehimr
发布于 2019/03/22 11:14
字数 790
阅读 9
收藏 0

精选30+云产品,助力企业轻松上云!>>>

 

expr_without_variable    { Z_LVAL($$.u.constant) = 1;  zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |    variable                { Z_LVAL($$.u.constant) = 1;  zend_do_pass_param(&$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |    '&' w_variable                 { Z_LVAL($$.u.constant) = 1;  zend_do_pass_param(&$2, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |    non_empty_function_call_parameter_list ',' expr_without_variable    { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1;  zend_do_pass_param(&$3, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |    non_empty_function_call_parameter_list ',' variable                    { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1;  zend_do_pass_param(&$3, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
    |    non_empty_function_call_parameter_list ',' '&' w_variable            { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1;  zend_do_pass_param(&$4, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
;

 

 

 

 将参数从左到在依次放到栈里

 

static int ZEND_FASTCALL  ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    {
        zval *valptr;
        zval *value;


        value = opline->op1.zv;

        ALLOC_ZVAL(valptr);
        INIT_PZVAL_COPY(valptr, value);
        if (!0) {
            zval_copy_ctor(valptr);
        }
        zend_vm_stack_push(valptr TSRMLS_CC);

    }

    ZEND_VM_NEXT_OPCODE();
}

 

 

static zend_always_inline void zend_vm_stack_push(void *ptr TSRMLS_DC)
{
    *(EG(argument_stack)->top++) = ptr;
}

 

 

 当调用函数时,将

static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
{
    USE_OPLINE
    zend_bool should_change_scope = 0;
    zend_function *fbc = EX(function_state).function;

    SAVE_OPLINE();
    EX(object) = EX(call)->object;
    if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
            zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
            CHECK_EXCEPTION();
            ZEND_VM_NEXT_OPCODE(); /* Never reached */
        }
        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
            zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
                fbc->common.scope ? fbc->common.scope->name : "",
                fbc->common.scope ? "::" : "",
                fbc->common.function_name);
        }
    }
    if (fbc->common.scope &&
        !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
        !EX(object)) {

        if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
            /* FIXME: output identifiers properly */
            zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name);
        } else {
            /* FIXME: output identifiers properly */
            /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
            zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name);
        }
    }

    if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
        should_change_scope = 1;
        EX(current_this) = EG(This);
        EX(current_scope) = EG(scope);
        EX(current_called_scope) = EG(called_scope);
        EG(This) = EX(object);
        EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
        EG(called_scope) = EX(call)->called_scope;
    }

    EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C);
    zend_vm_stack_push((void*)(zend_uintptr_t)opline->extended_value TSRMLS_CC);
    LOAD_OPLINE();

    if (fbc->type == ZEND_INTERNAL_FUNCTION) {

    } else if (fbc->type == ZEND_USER_FUNCTION) {
        temp_variable *ret = &EX_T(opline->result.var);
        EX(original_return_value) = EG(return_value_ptr_ptr);
        EG(active_symbol_table) = NULL;
        EG(active_op_array) = &fbc->op_array;
        EG(return_value_ptr_ptr) = NULL;


        if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) {

        } else if (EXPECTED(zend_execute_ex == execute_ex)) {
    
        } else {
            zend_execute(EG(active_op_array) TSRMLS_CC);
        }

        EG(opline_ptr) = &EX(opline);
        EG(active_op_array) = EX(op_array);
        EG(return_value_ptr_ptr) = EX(original_return_value);
        if (EG(active_symbol_table)) {
            zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
        }
        EG(active_symbol_table) = EX(symbol_table);
    } else { /* ZEND_OVERLOADED_FUNCTION */
        
    }

    EX(function_state).function = (zend_function *) EX(op_array);
    EX(function_state).arguments = NULL;



    EX(call)--;

    //删除栈中的数据
    zend_vm_stack_clear_multiple(1 TSRMLS_CC);

    ZEND_VM_NEXT_OPCODE();
}

 

 

static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC)
{
    void **p = EG(argument_stack)->top - 1;
     void **end = p - (int)(zend_uintptr_t)*p;

    while (p != end) {
        zval *q = (zval *) *(--p);
        *p = NULL;
        i_zval_ptr_dtor(q ZEND_FILE_LINE_CC);
    }
    if (nested) {
        EG(argument_stack)->top = p;
    } else {
        zend_vm_stack_free_int(p TSRMLS_CC);
    }
}

 

 

 

 

 

non_empty_parameter_list:
        optional_class_type T_VARIABLE                { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$2, &$$, NULL, &$1, 0 TSRMLS_CC); }
    |    optional_class_type '&' T_VARIABLE            { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV, &$3, &$$, NULL, &$1, 1 TSRMLS_CC); }
    |    optional_class_type '&' T_VARIABLE '=' static_scalar            { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$3, &$$, &$5, &$1, 1 TSRMLS_CC); }
    |    optional_class_type T_VARIABLE '=' static_scalar                { $$.op_type = IS_UNUSED; $$.u.op.num=1; zend_do_receive_arg(ZEND_RECV_INIT, &$2, &$$, &$4, &$1, 0 TSRMLS_CC); }
    |    non_empty_parameter_list ',' optional_class_type T_VARIABLE     { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$4, &$$, NULL, &$3, 0 TSRMLS_CC); }
    |    non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE    { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV, &$5, &$$, NULL, &$3, 1 TSRMLS_CC); }
    |    non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE     '=' static_scalar { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$5, &$$, &$7, &$3, 1 TSRMLS_CC); }
    |    non_empty_parameter_list ',' optional_class_type T_VARIABLE '=' static_scalar     { $$=$1; $$.u.op.num++; zend_do_receive_arg(ZEND_RECV_INIT, &$4, &$$, &$6, &$3, 0 TSRMLS_CC); }
;

 

void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, const znode *initialization, znode *class_type, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
{
    zend_op *opline;
    zend_arg_info *cur_arg_info;
    znode var;
 {
        var.op_type = IS_CV;
        var.u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len, 0 TSRMLS_CC);
        Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
        var.EA = 0;
        if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
            Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
            !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
            if (CG(active_op_array)->scope &&
                (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
                zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
            }
            CG(active_op_array)->this_var = var.u.op.var;
        }
    }

    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
    CG(active_op_array)->num_args++;
    opline->opcode = op;
    SET_NODE(opline->result, &var);
    SET_NODE(opline->op1, offset);
    if (op == ZEND_RECV_INIT) {
        SET_NODE(opline->op2, initialization);
    } else {
        CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
        SET_UNUSED(opline->op2);
    }
    CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
    cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
    cur_arg_info->name = zend_new_interned_string(estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len), varname->u.constant.value.str.len + 1, 1 TSRMLS_CC);
    cur_arg_info->name_len = varname->u.constant.value.str.len;
    cur_arg_info->type_hint = 0;
    cur_arg_info->allow_null = 1;
    cur_arg_info->pass_by_reference = pass_by_reference;
    cur_arg_info->class_name = NULL;
    cur_arg_info->class_name_len = 0;
}

 

 

 

 

static int ZEND_FASTCALL  ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    USE_OPLINE
    zend_uint arg_num = opline->op1.num;

    //得到参数
    zval **param = zend_vm_stack_get_arg(arg_num TSRMLS_CC);

    SAVE_OPLINE();
    if (UNEXPECTED(param == NULL)) {

    } else {
        zval **var_ptr;

        zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC);
        var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
        Z_DELREF_PP(var_ptr);
        *var_ptr = *param;
        Z_ADDREF_PP(var_ptr);
    }

    CHECK_EXCEPTION();
    ZEND_VM_NEXT_OPCODE();
}

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
C++ std::function 和 std::bind

C++11提供了std::function和std::bind两个工具,用于引用可调用对象。这些可调用对象包括 普通函数,Lambda表达式,类的静态成员函数,非静态成员函数以及仿函数等。引用可调用对象,可以用于...

yepanl
2018/09/23
179
0
[PHP] PHP源码常用代码中的宏定义

PHP源码常用代码宏定义: #define 宏名 字符串 #表示这是一条预处理命令,所有的预处理命令都以#开头。define是预处理命令。宏名是标识符的一种,命名规则和标识符相同。字符串可以是常数、表...

冻结not
2019/10/16
42
0
jQuery基础效果

jQuery基础效果 $(document).ready(function(){}这句话的意思是页面加载完成后执行, 等同于js中的window.onload,大家学了jQuery的话应该就会知道 $(document).ready(function(){//这行代码...

新网学会
2017/12/11
0
0
VBS中Sub与Function的区别[资料]

VBS中Sub与Function的区别[资料] 在VBscript中,有两种procedure:Sub procedure与Function procedure。 一、Sub Procedures VBScript的Sub Procedure以Sub开始,以End Sub结束,中间是VBS...

不折腾难受斯基
2015/07/23
46
0
微信小程序 - Request | 路由跳转 | 本地存储

Request 官方文档 wx.request相当于发送ajax请求 参数 属性 类型 默认值 必填 说明 url string 是 开发者服务器接口地址 data string/object/ArrayBuffer 否 请求的参数 header Object 否 设...

osc_k9z4xzi8
2019/11/05
2
0

没有更多内容

加载失败,请刷新页面

加载更多

在Bash脚本中,如果发生某种情况,如何退出整个脚本?

问题: I'm writing a script in Bash to test some code. 我正在Bash中编写脚本来测试一些代码。 However, it seems silly to run the tests if compiling the code fails in the first pl......

技术盛宴
11分钟前
7
0
Windows安装Python+OpenCV

1、更新PyCharm中pip来源,使用清华和阿里云:https://pypi.tuna.tsinghua.edu.cn/simple/ http://mirrors.aliyun.com/pypi/simple/ 2、PyCharm查看已安装packets,添加新的安装包,从pip云端...

极客行
34分钟前
17
0
tomcat8配置虚拟目录,实现一个tomcat运行两个项目, tomcat配置URL不区分大小写

<?xml version="1.0" encoding="UTF-8"?><!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distri......

青峰Jun19er
40分钟前
19
0
HBase和MySQL存储方式的差别?或者说是,行存储和列存储的区别?

HBase借鉴列存储的思想,但是最底层依然是依靠键值对来存储数据,HBase为非关系型数据库 而MySQL则是行存储,MySQL为关系型数据库 写过程 行存储因为数据是连续的,所以只需要进行追加即可;...

其乐m
45分钟前
25
0
一个老程序员在互联网寒冬下的感悟

1. 你千万不要认为学习技术就可以换来稳定的生活和高的薪水待遇,你更不要认为那些从事市场开发,跑腿的人,没有前途。 不清楚你是不是知道,咱们中国有相当大的一部分软件公司,他们的软件开...

北柠Java
49分钟前
39
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部