亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > PHP > 正文

PHP內核學習教程之php opcode內核實現

2024-05-04 23:42:37
字體:
來源:轉載
供稿:網友
opcode是計算機指令中的一部分,用于指定要執行的操作, 指令的格式和規范由處理器的指令規范指定,通過本文給大家介紹PHP內核學習教程之php opcode內核實現,感興趣的朋友一起學習吧
 

opcode是計算機指令中的一部分,用于指定要執行的操作, 指令的格式和規范由處理器的指令規范指定。 除了指令本身以外通常還有指令所需要的操作數,可能有的指令不需要顯式的操作數。 這些操作數可能是寄存器中的值,堆棧中的值,某塊內存的值或者IO端口中的值等等。

通常opcode還有另一種稱謂:字節碼(byte codes)。 例如Java虛擬機(JVM),.NET的通用中間語言(CIL: Common Intermeditate Language)等等。

1. Opcode簡介

opcode是計算機指令中的一部分,用于指定要執行的操作, 指令的格式和規范由處理器的指令規范指定。 除了指令本身以外通常還有指令所需要的操作數,可能有的指令不需要顯式的操作數。 這些操作數可能是寄存器中的值,堆棧中的值,某塊內存的值或者IO端口中的值等等 

通常opcode還有另一種稱謂: 字節碼(byte codes)。 例如Java虛擬機(JVM),.NET的通用中間語言(CIL: Common Intermeditate Language)等等 

PHP中的opcode則屬于前面介紹中的后著,PHP是構建在Zend虛擬機(Zend VM)之上的。PHP的opcode就是Zend虛擬機中的指令(基于Zend的中間代碼)

Relevant Link:

http://www.luocong.com/learningopcode/doc/1._%E4%BB%80%E4%B9%88%E6%98%AFOpCode%EF%BC%9F.htm

2. PHP中的Opcode

0x1: 數據結構

在PHP實現內部,opcode由如下的結構體表示

/php-5.6.17/Zend/zend_compile.h

struct _zend_op {opcode_handler_t handler; // 執行該opcode時調用的處理函數znode_op op1; // opcode所操作的操作數znode_op op2; // opcode所操作的操作數znode_op result;ulong extended_value;uint lineno;zend_uchar opcode; // opcode代碼zend_uchar op1_type;zend_uchar op2_type;zend_uchar result_type;}; 

和CPU的指令類似,有一個標示指令的opcode字段,以及這個opcode所操作的操作數,PHP不像匯編那么底層, 在腳本實際執行的時候可能還需要其他更多的信息,extended_value字段就保存了這類信息, 其中的result域則是保存該指令執行完成后的結果

例如如下代碼是在編譯器遇到print語句的時候進行編譯的函數

/php-5.6.17/Zend/zend_compile.c

void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */{ //新創建一條zend_op zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);//將新建的zend_op的返回值類型設置為臨時變量(IS_TMP_VAR),因為print中的內存僅僅為了臨時輸出,并不需要保存opline->result_type = IS_TMP_VAR;//為臨時變量申請空間opline->result.var = get_temporary_variable(CG(active_op_array));//指定opcode為ZEND_PRINTopline->opcode = ZEND_PRINT;//將傳遞進來的參數賦值給這條opcode的第一個操作數SET_NODE(opline->op1, arg);SET_UNUSED(opline->op2);GET_NODE(result, opline->result);}

 

0x2: opcode類型: zend_op->zend_uchar opcode

比對匯編語言的概念,每個opcode都對應于一個類型,表明該opcpde的"操作指令",opcode的類型為zend_uchar,zend_uchar實際上就是unsigned char,此字段保存的整形值即為op的編號,用來區分不同的op類型,opcode的可取值都被定義成了宏

/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_SL 6#define ZEND_SR 7#define ZEND_CONCAT 8#define ZEND_BW_OR 9#define ZEND_BW_AND 10#define ZEND_BW_XOR 11#define ZEND_BW_NOT 12#define ZEND_BOOL_NOT 13#define ZEND_BOOL_XOR 14#define ZEND_IS_IDENTICAL 15#define ZEND_IS_NOT_IDENTICAL 16#define ZEND_IS_EQUAL 17#define ZEND_IS_NOT_EQUAL 18#define ZEND_IS_SMALLER 19#define ZEND_IS_SMALLER_OR_EQUAL 20#define ZEND_CAST 21#define ZEND_QM_ASSIGN 22#define ZEND_ASSIGN_ADD 23#define ZEND_ASSIGN_SUB 24#define ZEND_ASSIGN_MUL 25#define ZEND_ASSIGN_DIV 26#define ZEND_ASSIGN_MOD 27#define ZEND_ASSIGN_SL 28#define ZEND_ASSIGN_SR 29#define ZEND_ASSIGN_CONCAT 30#define ZEND_ASSIGN_BW_OR 31#define ZEND_ASSIGN_BW_AND 32#define ZEND_ASSIGN_BW_XOR 33#define ZEND_PRE_INC 34#define ZEND_PRE_DEC 35#define ZEND_POST_INC 36#define ZEND_POST_DEC 37#define ZEND_ASSIGN 38#define ZEND_ASSIGN_REF 39#define ZEND_ECHO 40#define ZEND_PRINT 41#define ZEND_JMP 42#define ZEND_JMPZ 43#define ZEND_JMPNZ 44#define ZEND_JMPZNZ 45#define ZEND_JMPZ_EX 46#define ZEND_JMPNZ_EX 47#define ZEND_CASE 48#define ZEND_SWITCH_FREE 49#define ZEND_BRK 50#define ZEND_CONT 51#define ZEND_BOOL 52#define ZEND_INIT_STRING 53#define ZEND_ADD_CHAR 54#define ZEND_ADD_STRING 55#define ZEND_ADD_VAR 56#define ZEND_BEGIN_SILENCE 57#define ZEND_END_SILENCE 58#define ZEND_INIT_FCALL_BY_NAME 59#define ZEND_DO_FCALL 60#define ZEND_DO_FCALL_BY_NAME 61#define ZEND_RETURN 62#define ZEND_RECV 63#define ZEND_RECV_INIT 64#define ZEND_SEND_VAL 65#define ZEND_SEND_VAR 66#define ZEND_SEND_REF 67#define ZEND_NEW 68#define ZEND_INIT_NS_FCALL_BY_NAME 69#define ZEND_FREE 70#define ZEND_INIT_ARRAY 71#define ZEND_ADD_ARRAY_ELEMENT 72#define ZEND_INCLUDE_OR_EVAL 73#define ZEND_UNSET_VAR 74#define ZEND_UNSET_DIM 75#define ZEND_UNSET_OBJ 76#define ZEND_FE_RESET 77#define ZEND_FE_FETCH 78#define ZEND_EXIT 79#define ZEND_FETCH_R 80#define ZEND_FETCH_DIM_R 81#define ZEND_FETCH_OBJ_R 82#define ZEND_FETCH_W 83#define ZEND_FETCH_DIM_W 84#define ZEND_FETCH_OBJ_W 85#define ZEND_FETCH_RW 86#define ZEND_FETCH_DIM_RW 87#define ZEND_FETCH_OBJ_RW 88#define ZEND_FETCH_IS 89#define ZEND_FETCH_DIM_IS 90#define ZEND_FETCH_OBJ_IS 91#define ZEND_FETCH_FUNC_ARG 92#define ZEND_FETCH_DIM_FUNC_ARG 93#define ZEND_FETCH_OBJ_FUNC_ARG 94#define ZEND_FETCH_UNSET 95#define ZEND_FETCH_DIM_UNSET 96#define ZEND_FETCH_OBJ_UNSET 97#define ZEND_FETCH_DIM_TMP_VAR 98#define ZEND_FETCH_CONSTANT 99#define ZEND_GOTO 100#define ZEND_EXT_STMT 101#define ZEND_EXT_FCALL_BEGIN 102#define ZEND_EXT_FCALL_END 103#define ZEND_EXT_NOP 104#define ZEND_TICKS 105#define ZEND_SEND_VAR_NO_REF 106#define ZEND_CATCH 107#define ZEND_THROW 108#define ZEND_FETCH_CLASS 109#define ZEND_CLONE 110#define ZEND_RETURN_BY_REF 111#define ZEND_INIT_METHOD_CALL 112#define ZEND_INIT_STATIC_METHOD_CALL 113#define ZEND_ISSET_ISEMPTY_VAR 114#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115#define ZEND_PRE_INC_OBJ 132#define ZEND_PRE_DEC_OBJ 133#define ZEND_POST_INC_OBJ 134#define ZEND_POST_DEC_OBJ 135#define ZEND_ASSIGN_OBJ 136#define ZEND_INSTANCEOF 138#define ZEND_DECLARE_CLASS 139#define ZEND_DECLARE_INHERITED_CLASS 140#define ZEND_DECLARE_FUNCTION 141#define ZEND_RAISE_ABSTRACT_ERROR 142#define ZEND_DECLARE_CONST 143#define ZEND_ADD_INTERFACE 144#define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145#define ZEND_VERIFY_ABSTRACT_CLASS 146#define ZEND_ASSIGN_DIM 147#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148#define ZEND_HANDLE_EXCEPTION 149#define ZEND_USER_OPCODE 150#define ZEND_JMP_SET 152#define ZEND_DECLARE_LAMBDA_FUNCTION 153#define ZEND_ADD_TRAIT 154#define ZEND_BIND_TRAITS 155#define ZEND_SEPARATE 156#define ZEND_QM_ASSIGN_VAR 157#define ZEND_JMP_SET_VAR 158#define ZEND_DISCARD_EXCEPTION 159#define ZEND_YIELD 160#define ZEND_GENERATOR_RETURN 161#define ZEND_FAST_CALL 162#define ZEND_FAST_RET 163#define ZEND_RECV_VARIADIC 164#define ZEND_SEND_UNPACK 165#define ZEND_POW 166#define ZEND_ASSIGN_POW 167 

0x3: opcode執行句柄: zend_op->handler

op的執行句柄,其類型為opcode_handler_t

typedef int (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); 
這個函數指針為op定義了執行方式,每一種opcode字段都對應一個種類的handler,比如如果$a = 1;這樣的代碼生成的op,操作數為const和cv,最后就能確定handler為函數ZEND_ASSIGN_SPEC_CV_CONST_HANDLER

/Zend/zend_vm_execute.h

void zend_init_opcodes_handlers(void){static const opcode_handler_t labels[] = {..ZEND_ASSIGN_SPEC_CV_CONST_HANDLER,..}}

0x4: opcpde操作數znode

操作數字段是_zend_op類型中比較重要的部分了,其中op1,op2,result三個操作數定義為znode類型 

/php-5.6.17/Zend/zend_compile.h

typedef struct _znode { /* used only during compilation *//*這個int類型的字段定義znode操作數的類型#define IS_CONST (1<<0) //表示常量,例如$a = 123; $b = "hello";這些代碼生成OP后,123和"hello"都是以常量類型操作數存在#define IS_TMP_VAR (1<<1) //表示臨時變量,臨時變量一般在前面加~來表示,這是一些OP執行過程中需要用到的中間變量,例如初始化一個數組的時候,就需要一個臨時變量來暫時存儲數組zval,然后將數組賦值給變量#define IS_VAR (1<<2) //一般意義上的變量,以$開發表示#define IS_UNUSED (1<<3) // Unused variable #define IS_CV (1<<4) // Compiled variable,這種類型的操作數比較重要,此類型是在PHP后來的版本中(大概5.1)中才出現,CV的意思是compiled variable,即編譯后的變量,變量都是保存在一個符號表中,這個符號表是一個哈希表,如果每次讀寫變量的時候都需要到哈希表中去檢索,會對效率有一定的影響,因此在執行上下文環境中,會將一些編譯期間生成的變量緩存起來。此類型操作數一般以!開頭表示,比如變量$a=123;$b="hello"這段代碼,$a和$b對應的操作數可能就是!0和!1, 0和1相當于一個索引號,通過索引號從緩存中取得相應的值*/int op_type;/*此字段為一個聯合體,根據op_type的不同,u取不同的值1. op_type=IS_CONST的時候,u中的constant保存的就是操作數對應的zval結構2. 例如$a=123時,123這個操作數中,u中的constant是一個IS_LONG類型的zval,其值lval為123 */union {znode_op op;zval constant; /* replaced by literal/zv */zend_op_array *op_array;zend_ast *ast;} u;zend_uint EA; /* extended attributes */} znode; 

0x5: opcode編譯后數組op_array

在zend_do_print函數中的第一行,我們注意到下面這行代碼

zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); 

PHP腳本代碼被編譯后產生的opcode保存在op_array中,其內部存儲的結構如下

/php-5.6.17/Zend/zend_compile.h

struct _zend_op_array {/* Common elements */zend_uchar type;const char *function_name; // 如果是用戶定義的函數則,這里將保存函數的名字zend_class_entry *scope;zend_uint fn_flags;union _zend_function *prototype;zend_uint num_args;zend_uint required_num_args;zend_arg_info *arg_info;/* END of common elements */zend_uint *refcount;zend_op *opcodes; // opcode數組zend_uint last;zend_compiled_variable *vars;int last_var;zend_uint T;zend_uint nested_calls;zend_uint used_stack;zend_brk_cont_element *brk_cont_array;int last_brk_cont;zend_try_catch_element *try_catch_array;int last_try_catch;zend_bool has_finally_block;/* static variables support */HashTable *static_variables;zend_uint this_var;const char *filename;zend_uint line_start;zend_uint line_end;const char *doc_comment;zend_uint doc_comment_len;zend_uint early_binding; /* the linked list of delayed declarations */zend_literal *literals;int last_literal;void **run_time_cache;int last_cache_slot;void *reserved[ZEND_MAX_RESERVED_RESOURCES];}; 

整個PHP腳本代碼被編譯后的opcodes保存在這里,在執行的時候由下面的execute函數執行

ZEND_API void execute(zend_op_array *op_array TSRMLS_DC){// ... 循環執行op_array中的opcode或者執行其他op_array中的opcode}

每條opcode都有一個opcode_handler_t的函數指針字段,用于執行該opcode,PHP有三種方式來進行opcode的處理

1. CALL: PHP默認使用CALL的方式,也就是函數調用的方式
2. SWITCH: 由于opcode執行是每個PHP程序頻繁需要進行的操作,可以使用SWITCH或者GOTO的方式來分發
3. GOTO: 通常GOTO的效率相對會高一些,不過效率是否提高依賴于不同的CPU 
實際上我們會發現,在/zend/zend_language_parser.c中就是Zend的opcode翻譯解釋執行過程,其中包含了call、switch、goto三種opcode執行方式

這就是PHP為什么稱之為解釋型語言的內核原理,PHP在完成Lex詞法解析后,在語法解析即生成產生式的時候,直接通過call、switch、goto的方式調用zend api進行即使解釋執行

Relevant Link:

http://www.nowamagic.net/librarys/veda/detail/1325http://php.net/manual/zh/internals2.opcodes.list.phphttp://www.nowamagic.net/librarys/veda/detail/1543http://www.nowamagic.net/librarys/veda/detail/1324http://www.nowamagic.net/librarys/veda/detail/1543 http://www.laruence.com/2008/06/18/221.htmlhttp://www.php-internals.com/book/?p=chapt02/02-03-02-opcode 

3. opcode翻譯執行(即時解釋執行)

Relevant Link:

http://www.php-internals.com/book/?p=chapt02/02-03-03-from-opcode-to-handler

以上所述本文給大家介紹的PHP內核學習教程之php opcode內核實現的相關知識,希望對大家有所幫助。



注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频一| 国产三级精品网站| 亚洲天堂成人在线视频| 日韩免费在线观看视频| 日韩精品视频在线观看免费| 成人黄色午夜影院| 久久躁狠狠躁夜夜爽| 亚洲国产精品久久久久秋霞蜜臀| 欧美洲成人男女午夜视频| 91禁外国网站| 欧美日韩国产成人| 国产精品第七影院| 日本19禁啪啪免费观看www| 亚洲成av人影院在线观看| 午夜精品久久久久久久男人的天堂| 中文字幕日韩有码| 国产精品一区二区3区| 日韩大胆人体377p| 久久久国产一区二区三区| 亚洲伦理中文字幕| 精品久久久久久久久国产字幕| 国产专区欧美专区| 亚洲嫩模很污视频| 午夜精品在线观看| 欧美日韩国产精品| 亚洲欧美制服丝袜| 日韩免费av片在线观看| 久久色精品视频| 欧美精品久久久久久久久| 久久天天躁狠狠躁夜夜爽蜜月| 亚洲免费视频网站| 日韩精品视频在线免费观看| 日日狠狠久久偷偷四色综合免费| 国产精品成久久久久三级| 成人免费看黄网站| 日韩免费av在线| 国产成人av网址| 欧美激情xxxx| 中文字幕一区电影| xx视频.9999.com| 操人视频在线观看欧美| 亚洲iv一区二区三区| 久久五月情影视| 国产精品久久久久久av福利| 欧美激情videos| 精品国产欧美一区二区三区成人| 77777亚洲午夜久久多人| 成人亚洲欧美一区二区三区| 清纯唯美亚洲激情| 久久精品国产成人精品| 欧美亚洲成人xxx| 亚洲国模精品私拍| 日本不卡视频在线播放| 日本精品久久中文字幕佐佐木| 在线免费观看羞羞视频一区二区| 国产精品影片在线观看| 庆余年2免费日韩剧观看大牛| www.久久色.com| 国产亚洲xxx| 国产丝袜一区二区三区| 超碰91人人草人人干| 成人天堂噜噜噜| 91在线精品视频| 欧美亚洲另类制服自拍| 精品一区二区三区四区在线| 97激碰免费视频| 中文字幕欧美专区| 久久夜精品va视频免费观看| 深夜成人在线观看| 久久久伊人日本| 日韩一区av在线| 亚洲精品电影在线| 欧美日韩一区二区精品| 欧美电影在线观看完整版| 欧美插天视频在线播放| 在线观看欧美日韩国产| 欧美一级免费视频| 国产精品免费视频xxxx| 欧美肥老妇视频| 久久黄色av网站| 亚洲午夜av电影| 国模视频一区二区| 日韩亚洲在线观看| 久久久久久香蕉网| 国产精品视频网站| 国产精品视频内| 疯狂做受xxxx高潮欧美日本| 91精品国产综合久久男男| 久久国产精品首页| 亚洲美女www午夜| 国产精品盗摄久久久| 国产日本欧美一区二区三区| 久久久国产精彩视频美女艺术照福利| 日韩成人高清在线| 欧美日韩成人在线播放| 国产精品久久77777| 中文字幕亚洲欧美日韩在线不卡| 一区二区欧美日韩视频| 国外视频精品毛片| 欧美精品久久一区二区| 国产精品老女人精品视频| 日产精品99久久久久久| 疯狂做受xxxx高潮欧美日本| 欧美劲爆第一页| 欧美一性一乱一交一视频| 国产视频久久久久久久| 日韩成人免费视频| 国产婷婷成人久久av免费高清| 亚洲激情久久久| 亚洲а∨天堂久久精品喷水| 日韩精品黄色网| 欧美色视频日本高清在线观看| 久久国产精品久久久久久| 欧美专区在线观看| 国产福利精品视频| 18性欧美xxxⅹ性满足| 国内成人精品一区| 久久久久久亚洲精品中文字幕| 色哟哟网站入口亚洲精品| 色综合色综合久久综合频道88| 亚洲福利在线观看| 日韩最新免费不卡| 国产精品嫩草影院一区二区| 亚洲精品资源美女情侣酒店| 中文字幕亚洲情99在线| 国产精品久久久久久久天堂| 91香蕉电影院| 国产精品久久久久久久久久免费| 久久这里只有精品视频首页| 欧美另类极品videosbest最新版本| 亚洲欧洲自拍偷拍| 日韩免费观看网站| 日本一区二区在线免费播放| 日韩天堂在线视频| 伊人伊成久久人综合网站| 91九色国产在线| 日韩av免费在线播放| 国内精品模特av私拍在线观看| 人人澡人人澡人人看欧美| 亚洲区免费影片| 亚洲毛片在线看| 欧美一级电影在线| 国产精品自产拍在线观| 亚洲天堂av在线播放| 久久精品国产亚洲精品2020| 欧美在线视频网| 欧美国产高跟鞋裸体秀xxxhd| 成人免费网站在线观看| 欧美日韩精品在线观看| 国产欧美va欧美va香蕉在线| 亚洲第一福利在线观看| 911国产网站尤物在线观看| 国产性猛交xxxx免费看久久| 亚洲a中文字幕| 97国产真实伦对白精彩视频8| 91精品国产91久久久久| 中文字幕少妇一区二区三区| 亚洲欧美一区二区三区四区| 国产不卡av在线免费观看| 国产成人精品视| 91在线网站视频| 538国产精品一区二区免费视频| 亚洲电影免费观看高清完整版在线观看| 国产精品永久免费|