亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁技術(shù)文章
文章詳情頁

PHP內(nèi)核探索 —— 操作碼OpCode:計算機最終是執(zhí)行這些OpCode

瀏覽:25日期:2022-09-16 13:14:52

運行一段PHP代碼主要有兩個階段:編譯和執(zhí)行。 當(dāng)然編譯過程中還包括詞法分析語法分析不同階段和細節(jié),這里我們將其作為一個整體。在這兩個階段之間,PHP代碼會被編譯成opcode,可以將其認為是引擎的一個中間語言,編輯階段把PHP源碼生成opcode,然后在執(zhí)行階段執(zhí)行這些opcode。這篇文章將簡單的介紹opcode。

PHP代碼編譯之后會生成許多的op,每一個op都是一個zend_op類型的c變量。相關(guān)的定義可以在{PHPSRC}/Zend/zend_compile.h中看到:

struct _zend_op { opcode_handler_t handler; znode result; znode op1; znode op2; ulong extended_value; uint lineno; zend_uchar opcode; }; typedef struct _zend_op zend_op;

簡單的說說這幾個字段:

1. result,op1,op2

這三個字段都是znode類型,它們是op的操作數(shù)和操作結(jié)果載體,當(dāng)然并不是每個op都需要使用這三個字段,根據(jù)op的功能不同,會使用其中某些字段。比如類型為ZEND_ECHO的op值需要使用op1,功能就是將op1中的相應(yīng)的值輸出。一會再單獨介紹znode類型。

2. opcode

opcode的類型為zend_uchar,zend_uchar實際上就是unsigned char,此字段保存的整形值即為op的編號,用來區(qū)分不同的op類型,opcode的可取值都被定義成了宏,可以在{PHPSRC}/Zend/zend_vm_opcodes.h中看到這些宏的定義,類似如下:

#define ZEND_NOP 0 #define ZEND_ADD 1 #define ZEND_SUB 2 #define ZEND_MUL 3 #define ZEND_DIV 4 #define ZEND_MOD 5 #define ZEND_SL6 #define ZEND_SR7 #define ZEND_CONCAT 8 #define ZEND_BW_OR 9 #define ZEND_BW_AND 10 //......

3. handler

op的執(zhí)行句柄,其類型為opcode_handler_t,opcode_handler_t的類型定義為typedef int (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); 這個函數(shù)指針為op定義了執(zhí)行方式,每一種opcode字段都對應(yīng)一個種類的handler,比如opcode= 38 (ZEND_ASSIGN), 那么其對應(yīng)的handler對應(yīng)的就是static int ZEND_FASTCALL? ZEND_ASSIGN_**種類的handler,根據(jù)op操作數(shù)類型的不同,可以確定到這個種類中的某一個具體的函數(shù),比如如果$a = 1;這樣的代碼生成的op,操作數(shù)為const和cv,最后就能確定handler為函數(shù)ZEND_ASSIGN_SPEC_CV_CONST_HANDLER,這些handler函數(shù)都定義在{PHPSRC}/Zend/zend_vm_execute.h中,此文件可以由一個PHP腳本生成,其中也定義了通過op來映射得到其hander的算法。

4. lineno

op對應(yīng)源代碼文件中的行號。

5. extended_value

擴展字段暫時不介紹

操作數(shù)znode簡介

操作數(shù)字段是這個類型中比較重要的部分了,其中op1,op2,result三個操作數(shù)定義為znode類型,znode相關(guān)定義在此文件中:

typedef struct _znode { int op_type; union { zval constant; zend_uint var; zend_uint opline_num; /* Needs to be signed */ zend_op_array *op_array; zend_op *jmp_addr; struct { zend_uint var; /* dummy */ zend_uint type; } EA; } u; } znode;

znode類型中定義了兩個字段:

1. op_type

這個int類型的字段定義znode操作數(shù)的類型,這些類型的可取值的宏定義在此文件中

#define IS_CONST (1<<0) #define IS_TMP_VAR (1<<1) #define IS_VAR (1<<2) #define IS_UNUSED (1<<3) /* Unused variable */ #define IS_CV (1<<4) /* Compiled variable */IS_CONST:表示常量,例如$a = 123; $b = 'hello';這些代碼生成OP后,123和'hello'都是以常量類型操作數(shù)存在。IS_TMP_VAR:表示臨時變量,臨時變量一般在前面加~來表示,這是一些OP執(zhí)行過程中需要用到的中間變量,例如初始化一個數(shù)組的時候,就需要一個臨時變量來暫時存儲數(shù)組zval,然后將數(shù)組賦值給變量。IS_VAR:?一般意義上的變量,以$開發(fā)表示,此種變量本人目前研究的較少,暫不介紹IS_UNUSED :?暫時不介紹,從名字來看應(yīng)該是標(biāo)識為不使用IS_CV:這種類型的操作數(shù)比較重要,此類型是在PHP后來的版本中(大概5.1)中才出現(xiàn),CV的意思是compiled variable,即編譯后的變量,變量都是保存在一個符號表中,這個符號表是一個哈希表,試想如果每次讀寫變量的時候都需要到哈希表中去檢索,勢必會對效率有一定的影響,因此在執(zhí)行上下文環(huán)境中,會將一些編譯期間生成的變量緩存起來,此過程以后再詳細介紹。此類型操作數(shù)一般以!開頭表示,比如變量$a=123;$b='hello'這段代碼,$a和$b對應(yīng)的操作數(shù)可能就是!0和!1, 0和1相當(dāng)于一個索引號,通過索引號從緩存中取得相應(yīng)的值。

2. u

此字段為一個聯(lián)合體,根據(jù)op_type的不同,u取不同的值。比如op_type=IS_CONST的時候,u中的constant保存的就是操作數(shù)對應(yīng)的zval結(jié)構(gòu)。例如$a=123時,123這個操作數(shù)中,u中的constant是一個IS_LONG類型的zval,其值lval為123。

標(biāo)簽: PHP
相關(guān)文章:
主站蜘蛛池模板: 91精彩视频在线观看 | 视频在线观看黄 | 成 年 人 黄 片 大全 | wwxxx日本| 精品中文字幕制服中文 | 欧美精品一区二区三区免费观看 | 国产香蕉视频在线 | 国产一精品一av一免费爽爽 | 在线免费观看色视频 | chinese国产videoxx实拍 | 久久亚洲国产高清 | 黄视频在线观看网站 | 成人深夜福利在线播放不卡 | 日本黄色一级网站 | 国产图片区 | 中文字幕第一页在线 | 国产精品美女福利视频一区 | 欧美日韩亚洲国内综合网俺 | 国产一区精品 | 国产精品久久久久久久久久久搜索 | 多男一女一级淫片免费播放口 | 久久天堂成人影院 | 亚洲精品久久片久久 | 日韩字幕无线乱码 | 日韩亚洲综合精品国产 | 精品久久电影 | 国产成人免费观看在线视频 | 久久亚洲精品国产精品777777 | 国产视频福利一区 | 久久精品国产99久久6动漫欧 | 国产成人精品亚洲2020 | 成人三级做爰在线观看男女 | 精品免费久久 | 97国产大学生情侣11在线视频 | 久久夜色精品国产亚洲 | 久久久久久久国产精品影院 | 任你躁在线精品视频m3u8 | 国产精品视频成人 | 欧美一区二区三区久久综合 | 黄色片在线免费 | 国产成人a一区二区 |