struct _zend_op { // *opline *opcodes const void *handler; //指令執行handler znode_op op1; //運算元1 znode_op op2; //運算元型別實際就是個32位元整形,它主要用於儲存一些變數的索引位置、數值記錄等等 znode_op result; //返回值 uint32_t extended_value; uint32_t lineno; zend_uchar opcode; //opcode指令 zend_uchar op1_type; //運算元1型別 zend_uchar op2_type; zend_uchar result_type; //返回值型別 }; //運算元結構 //比如賦值語句:"$a = 45;",兩個運算元分別記錄"$a"、"45"的儲存位置,執行時根據op2取到值"45", //然後賦值給"$a",而"$a"的位置通過op1獲取到 //當然運算元並不是全部這麼用的,上面只是賦值時候的情況,其它操作會有不同的用法 //如函數呼叫時的傳參,op1記錄的就是傳遞的引數是第幾個,op2記錄的是引數的儲存位置, //result記錄的是函數接收引數的儲存位置。 typedef union _znode_op { //運算元型別實際就是個32位元整形,它主要用於儲存一些變數的索引位置、數值記錄等等 uint32_t constant; //運算元記錄著當前指令的關鍵資訊, 可以用於變數的儲存、存取 uint32_t var; uint32_t num; uint32_t opline_num; /* Needs to be signed */ #if ZEND_USE_ABS_JMP_ADDR zend_op *jmp_addr; #else uint32_t jmp_offset; #endif #if ZEND_USE_ABS_CONST_ADDR zval *zv; #endif } znode_op;
//運算元有5種不同的型別; #define IS_CONST (1<<0) //字面量,編譯時就可確定且不會改變的值,比如:$a = "hello~",其中字串"hello~"就是常數 #define IS_TMP_VAR (1<<1) //臨時變數 $a = "hello~" . time(),其中"hello~" . time()的值型別就是IS_TMP_VAR //"123" + $b的結果型別也是IS_TMP_VAR,從這兩個例子可以猜測,臨時變數多是執行期間其它 //型別組合現生成的一個中間值,由於它是現生成的,所以把IS_TMP_VAR賦值給IS_CV變數時不會增加其參照計數 #define IS_VAR (1<<2)//PHP變數 //這個很容易認為是PHP指令碼裡的變數,其實不是,這裡PHP變數的含義可以這樣理解:PHP變數是沒有顯 //式的在PHP指令碼中定義的,不是直接在程式碼通過$var_name定義的 //。這個型別最常見的例子是PHP函數的返回值,再如$a[0]陣列這種,它取出的值也是IS_VAR,再比如$$a這種 #define IS_UNUSED (1<<3) /* Unused variable */ //表示運算元沒有用 #define IS_CV (1<<4) /* Compiled variable */ //PHP指令碼變數,即指令碼裡通過$var_name定義的變數,這些變數是編譯階段確定的,所以是compile variable //result_type除了上面幾種型別外還有一種型別EXT_TYPE_UNUSED (1<<5),返回值沒有使用時會用到, //這個跟IS_UNUSED的區別是:IS_UNUSED表示本操作返回值沒有意義(也可簡單的認為沒有返回值), //而EXT_TYPE_UNUSED的含義是有返回值,但是沒有用到,比如函數返回值沒有接收
以上就是opcode 運算元 5 種不同的型別的詳細內容,更多請關注TW511.COM其它相關文章!