成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

(PHP7內(nèi)核剖析-7) Zend引擎執(zhí)行過程

elisa.yang / 2990人閱讀

1.EG(executor_globals/zend_executor_globals)

PHP整個(gè)生命周期中最主要的一個(gè)結(jié)構(gòu),是一個(gè)全局變量,在main執(zhí)行前分配(非ZTS下),直到PHP退出,它記錄著當(dāng)前請(qǐng)求全部的信息


2.EX(execute_data/zend_execute_data)

在執(zhí)行過程中最核心的一個(gè)結(jié)構(gòu),每次函數(shù)的調(diào)用、include/require、eval等都會(huì)生成一個(gè)新的結(jié)構(gòu),它表示當(dāng)前的作用域、代碼的執(zhí)行位置以及局部變量的分配等等,
#define EX(element)             ((execute_data)->element)

struct _zend_execute_data {
    const zend_op       *opline;  //指向當(dāng)前執(zhí)行的opcode,初始時(shí)指向zend_op_array起始位置
    zend_execute_data   *call;             /* current call                   */
    zval                *return_value;  //返回值指針
    zend_function       *func;          //當(dāng)前執(zhí)行的函數(shù)(非函數(shù)調(diào)用時(shí)為空)
    zend_class_entry    *called_scope;  //當(dāng)前call的類
    zend_execute_data   *prev_execute_data; //函數(shù)調(diào)用時(shí)指向調(diào)用位置作用空間
    zend_array          *symbol_table; //全局變量符號(hào)表
#if ZEND_EX_USE_RUN_TIME_CACHE
    void               **run_time_cache;   /* cache op_array->run_time_cache */
#endif
#if ZEND_EX_USE_LITERALS
    zval                *literals;  //字面量數(shù)組,與func.op_array->literals相同
#endif
};


3.Zend的執(zhí)行流程

在Zend VM中zend_execute_data的zend_execute_data.opline,zend_execute_data.prev_execute_data,實(shí)現(xiàn)了call/ret,后面會(huì)分配額外的內(nèi)存空間用于局部變量的存儲(chǔ),實(shí)現(xiàn)了ebp/esp的作用。
step1: 為當(dāng)前作用域分配一塊內(nèi)存,充當(dāng)運(yùn)行棧,zend_execute_data結(jié)構(gòu)、所有局部變量、中間變量等等都在此內(nèi)存上分配
step2: 初始化全局變量符號(hào)表,然后將全局執(zhí)行位置指針EG(current_execute_data)指向step1新分配的zend_execute_data,然后將zend_execute_data.opline指向op_array的起始位置
step3: 從EX(opline)開始調(diào)用各opcode的C處理handler(即_zend_op.handler),每執(zhí)行完一條opcode將EX(opline)++繼續(xù)執(zhí)行下一條,直到執(zhí)行完全部opcode,函數(shù)調(diào)用、if的執(zhí)行過程:
step3.1: if語(yǔ)句將根據(jù)條件的成立與否決定EX(opline) + offset所加的偏移量,實(shí)現(xiàn)跳轉(zhuǎn)
step3.2: 如果是函數(shù)調(diào)用,則首先從EG(function_table)中根據(jù)function_name取出此function對(duì)應(yīng)的編譯完成的zend_op_array,然后像step1一樣新分配一個(gè)zend_execute_data結(jié)構(gòu),
將EG(current_execute_data)賦值給新結(jié)構(gòu)的prev_execute_data,再將EG(current_execute_data)指向新的zend_execute_data,最后從新的zend_execute_data.opline開始執(zhí)行,切換
到函數(shù)內(nèi)部,函數(shù)執(zhí)行完以后將EG(current_execute_data)重新指向EX(prev_execute_data),釋放分配的運(yùn)行棧,銷毀局部變量,繼續(xù)從原來函數(shù)調(diào)用的位置執(zhí)行
step4: 全部opcode執(zhí)行完成后將step1分配的內(nèi)存釋放,這個(gè)過程會(huì)將所有的局部變量"銷毀",執(zhí)行階段結(jié)束


4.運(yùn)行時(shí)緩存

在執(zhí)行期間,PHP經(jīng)常需要根據(jù)名稱去不同的哈希表中查找常量、函數(shù)、類、成員方法、成員屬性等,因此PHP提供了一種緩存機(jī)制用于緩存根據(jù)名稱查找到的結(jié)果,以便再次執(zhí)行同一opcode時(shí)直接復(fù)用上次緩存的值,無(wú)需重復(fù)查找,從而提高執(zhí)行效率。運(yùn)行時(shí)緩存機(jī)制是在同一opcode執(zhí)行多次的情況下才會(huì)生效,特別注意這里的同一opcode指的并不是opcode值相同,而是指內(nèi)存里的同一份數(shù)據(jù)
實(shí)際上運(yùn)行時(shí)緩存是基于所屬opcode中CONST操作數(shù)存儲(chǔ)的,也就是說只有包含IS_CONST類型的操作數(shù)才有可能用到此機(jī)制,其它類型都不會(huì)用到,這是因?yàn)橹挥蠧ONST操作數(shù)是固定不變的,其它CV、VAR等類型值都不是固定的,既然其值是不固定的那么緩存的值也就不是固定的,所以不會(huì)針對(duì)CONST以外類型的opcode操作進(jìn)行緩存
緩存的存儲(chǔ)格式是一個(gè)數(shù)組,用于保存緩存的數(shù)據(jù)指針,而指針在數(shù)組中的起始存儲(chǔ)位置則保存在CONST操作數(shù)對(duì)應(yīng)的zval.u2.cache_slot中,實(shí)際上它是在編譯階段確定的,通過zend_op_array.cache_size記錄緩存可用起始位置,編譯過程中如果發(fā)現(xiàn)當(dāng)前操作適用緩存機(jī)制,則根據(jù)緩存數(shù)據(jù)的大小從cache_size開始分配8或16字節(jié)給那個(gè)操作數(shù),cache_size向后移動(dòng)對(duì)應(yīng)大小,然后將起始位置保存于CONST操作數(shù)的zval.u2.cache_slot中,執(zhí)行時(shí)直接根據(jù)這個(gè)值確定緩存位置。
緩存數(shù)據(jù)空間大小:
    8字節(jié):常量、函數(shù)、類
    16字節(jié):成員屬性、成員方法、類常量

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28588.html

相關(guān)文章

  • (PHP7內(nèi)核剖析-6) 函數(shù)

    摘要:引擎中定義了很多內(nèi)部函數(shù)供用戶在中使用,比如等等,除了引擎中定義的內(nèi)部函數(shù),擴(kuò)展中也提供了大量?jī)?nèi)部函數(shù),我們也可以靈活的通過擴(kuò)展自行定制。頭部是一個(gè)與完全相同的結(jié)構(gòu)函數(shù)指針,展開 1.函數(shù)的存儲(chǔ)結(jié)構(gòu) typedef union _zend_function zend_function; union _zend_function { zend_uchar typ...

    crelaber 評(píng)論0 收藏0
  • (PHP7內(nèi)核剖析-5) PHP代碼的編譯

    摘要:代碼的編譯的解析過程任務(wù)就是將代碼轉(zhuǎn)化為數(shù)組,代碼里的所有信息都保存在數(shù)組中,然后將數(shù)組交給引擎執(zhí)行,就是內(nèi)核具體執(zhí)行的命令,比如賦值加減操作函數(shù)調(diào)用等,每一條都對(duì)應(yīng)一個(gè)處理,這些是提前定義好的函數(shù)。 1.PHP代碼的編譯 PHP的解析過程任務(wù)就是將PHP代碼轉(zhuǎn)化為opcode數(shù)組,代碼里的所有信息都保存在opcode數(shù)組中,然后將opcode數(shù)組交給zend引擎執(zhí)行,opcode就是...

    DevTTL 評(píng)論0 收藏0
  • (PHP7內(nèi)核剖析-3) 變量

    摘要:插入一個(gè)元素時(shí)先將元素按先后順序插入數(shù)組,位置是,再根據(jù)的哈希值映射到散列表中的某個(gè)位置,將存入這個(gè)位置查找時(shí)先在散列表中映射到,得到在數(shù)組的位置,再?gòu)臄?shù)組中取出元素。目前只有兩種類型會(huì)使用這種機(jī)制。 1.變量結(jié)構(gòu) typedef struct _zval_struct zval; typedef union _zend_value { zend_long ...

    RiverLi 評(píng)論0 收藏0
  • (PHP7內(nèi)核剖析-8) 類

    摘要:父類方法為錯(cuò)誤,成員方法不得被重寫。父子類方法靜態(tài)屬性不一致父類方法為非靜態(tài)而子類的是靜態(tài)或相反,錯(cuò)誤。 1.類的結(jié)構(gòu) 類是編譯階段的產(chǎn)物,而對(duì)象是運(yùn)行時(shí)產(chǎn)生的,它們歸屬于不同階段。編譯完成后我們定義的每個(gè)類都會(huì)生成一個(gè)zend_class_entry,它保存著類的全部信息,在執(zhí)行階段所有類相關(guān)的操作都是用的這個(gè)結(jié)構(gòu), struct _zend_class_entry { ch...

    JohnLui 評(píng)論0 收藏0
  • (PHP7內(nèi)核剖析-4) 局部變量,全局變量,常量

    摘要:局部變量中局部變量分配在結(jié)構(gòu)上,每次執(zhí)行都會(huì)生成一個(gè)新的,局部變量在執(zhí)行之初分配,然后在執(zhí)行結(jié)束時(shí)釋放,這是局部變量的生命周期。 1.局部變量 PHP中局部變量分配在zend_execute_data結(jié)構(gòu)上,每次執(zhí)行zend_op_array都會(huì)生成一個(gè)新的zend_execute_data,局部變量在執(zhí)行之初分配,然后在執(zhí)行結(jié)束時(shí)釋放,這是局部變量的生命周期。 讀寫操作:局部變量通過...

    yagami 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<