首頁  >  文章  >  後端開發  >  PHP7核心剖析7之Zend引擎執行過程

PHP7核心剖析7之Zend引擎執行過程

不言
不言原創
2018-04-13 15:10:142151瀏覽

本篇文章的內容介紹的是關於PHP7核心剖析7之Zend引擎執行過程,現在分享給大家,有需要的朋友可以參考一下

1.EG(executor_globals/zend_executor_globals )

PHP整個生命週期中最主要的一個結構,是一個全域變量,在main執行前分配(非ZTS下),直到PHP退出,它記錄著目前請求全部的資訊

PHP7核心剖析7之Zend引擎執行過程


#2.EX(execute_data/zend_execute_data)

#在執行過程中最核心的一個結構,每次函數的呼叫、include/require、eval等都會產生一個新的結構,它表示目前的作用域、程式碼的執行位置以及局部變數的分配等等,
#define EX(element)             ((execute_data)->element)

struct _zend_execute_data {
    const zend_op       *opline;  //指向当前执行的opcode,初始时指向zend_op_array起始位置
    zend_execute_data   *call;             /* current call                   */
    zval                *return_value;  //返回值指针
    zend_function       *func;          //当前执行的函数(非函数调用时为空)
    zval                 This;          //这个值并不仅仅是面向对象的this,还有另外两个值也通过这个记录:call_info + num_args,分别存在zval.u1.reserved、zval.u2.num_args
    zend_class_entry    *called_scope;  //当前call的类
    zend_execute_data   *prev_execute_data; //函数调用时指向调用位置作用空间
    zend_array          *symbol_table; //全局变量符号表
#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;  //字面量数组,与func.op_array->literals相同
#endif
};

PHP7核心剖析7之Zend引擎執行過程


#3.Zend的執行流程

#在Zend VM中zend_execute_data的zend_execute_data.opline,zend_execute_data.prev_execute_data,實作了call/ret
step1: 为当前作用域分配一块内存,充当运行栈,zend_execute_data结构、所有局部变量、中间变量等等都在此内存上分配
step2: 初始化全局变量符号表,然后将全局执行位置指针EG(current_execute_data)指向step1新分配的zend_execute_data,然后将zend_execute_data.opline指向op_array的起始位置
step3: 从EX(opline)开始调用各opcode的C处理handler(即_zend_op.handler),每执行完一条opcode将EX(opline)++继续执行下一条,直到执行完全部opcode,函数/类成员方法调用、if的执行过程:
step3.1: if语句将根据条件的成立与否决定EX(opline) + offset所加的偏移量,实现跳转
step3.2: 如果是函数调用,则首先从EG(function_table)中根据function_name取出此function对应的编译完成的zend_op_array,然后像step1一样新分配一个zend_execute_data结构,
将EG(current_execute_data)赋值给新结构的prev_execute_data,再将EG(current_execute_data)指向新的zend_execute_data,最后从新的zend_execute_data.opline开始执行,切换
到函数内部,函数执行完以后将EG(current_execute_data)重新指向EX(prev_execute_data),释放分配的运行栈,销毁局部变量,继续从原来函数调用的位置执行
step4: 全部opcode执行完成后将step1分配的内存释放,这个过程会将所有的局部变量"销毁",执行阶段结束

PHP7核心剖析7之Zend引擎執行過程


##4 .運行時緩存

在執行期間,PHP經常需要根據名稱去不同的哈希表中查找常數、函數、類別、成員方法、成員屬性等,因此PHP提供了一種緩存機制用於快取根據名稱查找到的結果,以便再次執行同一opcode時直接重複使用上次快取的值,無需重複查找,從而提高執行效率。運行時快取機制是在同一opcode執行多次的情況下才會生效,特別注意這裡的同一opcode指的並不是opcode值相同,而是指內存裡的同一份資料實際上運行時緩存是基於所屬opcode中CONST運算元儲存的,也就是說只有包含IS_CONST類型的運算元才有可能用到此機制,其它型別都不會用到,這是因為只有CONST運算元是固定不變的,其它CV、VAR等類型值都不是固定的,既然其值是不固定的那麼快取的值也就不是固定的,所以不會針對CONST以外類型的opcode操作進行快取

相關推薦:

PHP7核心剖析6之函數

PHP7核心剖析5之PHP程式碼的編譯

############################################################################ PHP7核心剖析4之局部變數,全域變數,常數################

以上是PHP7核心剖析7之Zend引擎執行過程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn