php內核分析(八)-zend_compile


這里閱讀的php版本為PHP-7.1.0 RC3,閱讀代碼的平台為linux

回到之前看的zend_eval_stringl

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

zend_compile_string函數追下去可以追到compile_string

// 將一個字符串解析成為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了。這里的幾個點可以看看:

1 這么做類型轉換,參考convert_to_string。這個函數就是把任意類型的值轉換為zval的string類型。
2 zval_dtor,這個函數是能把任意的zval變量做回收。非常好用。
3 ZVAL_DUP,是進行復制,它和ZVAL_COPY的區別在於是否增加gc的引用計數。

下面又找到關鍵點:zend_compile


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM