zoukankan      html  css  js  c++  java
  • function参数

            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();
    }
  • 相关阅读:
    DP(第三版(较简单))
    【テンプレート】洛谷
    【説明する】并查集
    第一篇博文
    cogs 2398 切糕 最小割
    cogs 1873 happiness 最大权闭合子图
    cogs 1274 最小截断 最小割唯一判定
    cogs 736 星际转移 最大流
    cogs 329 K-联赛 最大流
    cogs 2605 寒假ing
  • 原文地址:https://www.cnblogs.com/taek/p/6722545.html
Copyright © 2011-2022 走看看