(PHP7內核剖析-6) 函數

1.函數的存儲結構數組

typedef union  _zend_function        zend_function;

union _zend_function {
    zend_uchar type;    
    struct {
        zend_uchar type; 
        zend_uchar arg_flags[3];
        uint32_t fn_flags;
        zend_string *function_name;
        zend_class_entry *scope; //成員方法所屬類,面向對象實現中用到
        union _zend_function *prototype;
        uint32_t num_args; //參數數量
        uint32_t required_num_args; //必傳參數數量
        zend_arg_info *arg_info; //參數信息
    } common;
    zend_op_array op_array; //自定義函數(函數實際編譯爲普通的zend_op_array)
    zend_internal_function internal_function; //內部函數(經過擴展或者內核提供的C函數)
};
zend_function.common.xx快速訪問到zend_function.zend_op_array.xx及zend_function.zend_internal_function.xx
zend_function.type取到zend_function.op_array.type及zend_function.internal_function.type

圖片描述

PHP在編譯階段將用戶自定義的函數編譯爲獨立的opcodes,保存在EG(function_table)中,調用時從新分配新的zend_execute_data(至關於運行棧),而後執行函數的opcodes,調用完再還原到舊的zend_execute_data,繼續執行,EG(function_table)是一個哈希表,記錄的就是PHP中全部的函數


2.函數參數函數

函數參數在內核實現上與函數內的局部變量實際是同樣的,提供一個單獨的編號,參數名稱也在zend_op_array.vars中,編號首先是從參數開始的,因此按照參數順序其編號依次爲0、一、2...(轉化爲相對內存偏移量就是9六、1十二、128...),而後函數調用時首先會在調用位置將參數的value複製到各參數各自的位置
//參數的額外信息
typedef struct _zend_arg_info {
    zend_string *name; //參數名
    zend_string *class_name;
    zend_uchar type_hint; //顯式聲明的參數類型,好比(array $param_1)
    zend_uchar pass_by_reference; //是否引用傳參,參數前加&的這個值就是1
    zend_bool allow_null; //是否容許爲NULL
    zend_bool is_variadic; //是否爲可變參數,即...用法,function my_func($a, ...$b){...}
} zend_arg_info;
每一個參數都有一個上面的結構,全部參數的結構保存在zend_op_array.arg_info數組中,這裏有一個地方須要注意:zend_op_array->arg_info數組保存的並不全是輸入參數,若是函數聲明瞭返回值類型則也會爲它建立一個zend_arg_info,這個結構在arg_info數組的第一個位置,這種狀況下zend_op_array->arg_info指向的實際是數組的第二個位置,返回值的結構經過zend_op_array->arg_info[-1]讀取


3.內部函數ui

內部函數指的是由內核、擴展提供的C語言編寫的function,這類函數不須要經歷opcode的編譯過程,因此效率上要高於PHP用戶自定義的函數,調用時與普通的C程序沒有差別。Zend引擎中定義了不少內部函數供用戶在PHP中使用,好比:define、defined、strlen、method_exists、class_exists、function_exists......等等,除了Zend引擎中定義的內部函數,PHP擴展中也提供了大量內部函數,咱們也能夠靈活的經過擴展自行定製。
//zend_internal_function頭部是一個與zend_op_array徹底相同的common結構
typedef struct _zend_internal_function {
    /* Common elements */
    zend_uchar type;
    zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */
    uint32_t fn_flags;
    zend_string* function_name;
    zend_class_entry *scope;
    zend_function *prototype;
    uint32_t num_args;
    uint32_t required_num_args;
    zend_internal_arg_info *arg_info;
    /* END of common elements */

    void (*handler)(INTERNAL_FUNCTION_PARAMETERS); //函數指針,展開:void (*handler)(zend_execute_data *execute_data, zval *return_value)
    struct _zend_module_entry *module;
    void *reserved[ZEND_MAX_RESERVED_RESOURCES];
} zend_internal_function;
相關文章
相關標籤/搜索