這裏閱讀的php版本爲PHP-7.1.0 RC3,閱讀代碼的平臺爲linuxphp
回到以前看的zend_eval_stringllinux
ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */ { ... new_op_array = zend_compile_string(&pv, string_name); // 這個是把php代碼編譯成爲opcode的過程 ... zend_execute(new_op_array, &local_retval); // 這個是具體的執行過程,執行opcode,把結果存儲到local_retval中 ... retval = SUCCESS; return retval; }
這裏的zend_execute執行了兩步,第一步是把php編譯解析成爲opcode的過程,咱們就先看這個。函數
zend_compile_string函數追下去能夠追到compile_stringrest
// 將一個字符串解析成爲op_array zend_op_array *compile_string(zval *source_string, char *filename) { zend_lex_state original_lex_state; zend_op_array *op_array = NULL; zval tmp; // 若是傳進來要解析的字符爲空,則返回null if (Z_STRLEN_P(source_string)==0) { return NULL; } ZVAL_DUP(&tmp, source_string); // 複製source_string到zval中 convert_to_string(&tmp); // 若是不是字符類型就轉換爲字符類型 source_string = &tmp; zend_save_lexical_state(&original_lex_state); // 保存lex上下文 if (zend_prepare_string_for_scanning(source_string, filename) == SUCCESS) { // 作編譯前的準備 BEGIN(ST_IN_SCRIPTING); // 設置狀態爲正在編譯 op_array = zend_compile(ZEND_EVAL_CODE); // 進行編譯,並把生成結果放在op_array中 } zend_restore_lexical_state(&original_lex_state); // 恢復lex上下文 zval_dtor(&tmp); // 釋放tmp return op_array; }
裏面最核心的就是zend_compile了。這裏的幾個點能夠看看:code
1 這麼作類型轉換,參考convert_to_string。這個函數就是把任意類型的值轉換爲zval的string類型。
2 zval_dtor,這個函數是能把任意的zval變量作回收。很是好用。
3 ZVAL_DUP,是進行復制,它和ZVAL_COPY的區別在因而否增長gc的引用計數。字符串
下面又找到關鍵點:zend_compilestring