[VLD(Vulcan Logic Dumper)](http://pecl.php.net/package/vld/)是一個掛鉤在Zend引擎下,并且輸出PHP腳本生成的中間代碼(執行單元)的擴展。它可以在一定程序上查看Zend引擎內部的一些實現原理,是我們學習PHP源碼的必備良器。它的作者是[Derick Rethans](http://derickrethans.nl/projects.html),除了VLD擴展,我們常用的[XDebug擴展](http://xdebug.org/)的也有該牛人的身影。
VLD擴展是一個開源的項目,在[這里](http://pecl.php.net/package/vld/)可以下載到最新的版本,雖然最新版本的更新也是一年前的事了。作者沒有提供編譯好的擴展,Win下使用VC6.0編譯生成dll文件。
*nix系統下直接configue,make,make install生成。如果遇到問題,請自行Google之。
看一個簡單的例子,假如存在t.php文件,其內容如下:
$a = 10;
echo $a;
在命令行下使用VLD擴展顯示信息。
php -dvld.active=1 t.php
-dvld.active=1表示激活VLD擴展,使用VLD擴展輸出中間代碼,此命令在CMD中輸出信息為:
Branch analysis from position: 0
Return found
filename: D:\work\xampp\xampp\php\t.php
function name: (null)
number of ops: 5
compiled vars: !0 = $a
line # * op fetch ext return operands
---------------------------------------------------------------------------------
2 0 > EXT_STMT
1 ASSIGN !0, 10
3 2 EXT_STMT
3 ECHO !0
4 4 > RETURN 1
?
branch: # 0; line: 2- 4; sop: 0; eop: 4
path #1: 0,
10
如上為VLD輸出的PHP代碼生成的中間代碼的信息,說明如下:
- Branch analysis from position 這條信息多在分析數組時使用。
- Return found 是否返回,這個基本上有都有。
- filename 分析的文件名
- function name 函數名,針對每個函數VLD都會生成一段如上的獨立的信息,這里顯示當前函數的名稱
- number of ops 生成的操作數
- compiled vars 編譯期間的變量,這些變量是在PHP5后添加的,它是一個緩存優化。這樣的變量在PHP源碼中以IS_CV標記。
- op list 生成的中間代碼的變量列表
使用-dvld.active參數輸出的是VLD默認設置,如果想看更加詳細的內容。可以使用-dvld.verbosity參數。
php -dvld.active=1 -dvld.verbosity=3 t.php
-dvld.verbosity=3或更大的值的效果都是一樣的,它們是VLD在當前版本可以顯示的最詳細的信息了,包括各個中間代碼的操作數等。顯示結果如下:
Finding entry points
Branch analysis from position: 0
Add 0
Add 1
Add 2
Add 3
Add 4
Return found
filename: D:\work\xampp\xampp\php\t.php
function name: (null)
number of ops: 5
compiled vars: !0 = $a
line # * op fetch ext return operands
--------------------------------------------------------------------------------
-
2 0 > EXT_STMT RES[ IS_UNUSED ] OP1[ IS_UNUSED ] OP2[ IS_UNUSED ]
1 ASSIGN OP1[IS_CV !0 ] OP2[ , IS_CONST (0) 10 ]
3 2 EXT_STMT RES[ IS_UNUSED ] OP1[ IS_UNUSED ] OP2[ IS_UNUSED ]
3 ECHO OP1[IS_CV !0 ]
4 > RETURN OP1[IS_CONST (0) 1 ]
?
branch: # 0; line: 2- 3; sop: 0; eop: 4
path #1: 0,
10
以上的信息與沒有加-dvld.verbosity=3的輸出相比,多了Add 字段,還有中間代碼的操作數的類型,如IS_CV,IS_CONST等。PHP代碼中的$a = 10; 其中10的類型為IS_CONST,$a作為一個編譯期間的一個緩存變量存在,其類型為IS_CV。
如果我們只是想要看輸出的中間代碼,并不想執行這段PHP代碼,可以使用-dvld.execute=0來禁用代碼的執行。
php -dvld.active=1 -dvld.execute=0 t.php
運行這個命令,你會發現這與最開始的輸出有一點點不同,它沒有輸出10。除了直接在屏幕上輸出以外,VLD擴展還支持輸出.dot文件,如下的命令:
php -dvld.active=1 -dvld.save_dir='D:\tmp' -dvld.save_paths=1 -dvld.dump_paths=1 t.php
以上的命令的意思是將生成的中間代碼的一些信息輸出在D:/tmp/paths.dot文件中。-dvld.save_dir指定文件輸出的路徑,-dvld.save_paths控制是否輸出文件,-dvld.dump_paths控制輸出的內容,現在只有0和1兩種情況。輸出的文件名已經在程序中硬編碼為paths.dot。這三個參數是相互依賴的關系,一般都會同時出現。
總結一下,VLD擴展的參數列表:
- -dvld.active 是否在執行PHP時激活VLD掛鉤,默認為0,表示禁用。可以使用-dvld.active=1啟用。
- -dvld.skip_prepend 是否跳過php.ini配置文件中[auto_prepend_file](http://php.net/auto-prepend-file)指定的文件,默認為0,即不跳過包含的文件,顯示這些包含的文件中的代碼所生成的中間代碼。此參數生效有一個前提條件:-dvld.execute=0
- -dvld.skip_append 是否跳過php.ini配置文件中[auto_append_file](http://php.net/auto-append-file)指定的文件,默認為0,即不跳過包含的文件,顯示這些包含的文件中的代碼所生成的中間代碼。此參數生效有一個前提條件:-dvld.execute=0
- -dvld.execute 是否執行這段PHP腳本,默認值為1,表示執行。可以使用-dvld.execute=0,表示只顯示中間代碼,不執行生成的中間代碼。
- -dvld.format 是否以自定義的格式顯示,默認為0,表示否。可以使用-dvld.format=1,表示以自己定義的格式顯示。這里自定義的格式輸出是以-dvld.col_sep指定的參數間隔
- -dvld.col_sep 在-dvld.format參數啟用時此函數才會有效,默認為 "\t"。
- -dvld.verbosity 是否顯示更詳細的信息,默認為1,其值可以為0,1,2,3 其實比0小的也可以,只是效果和0一樣,比如0.1之類,但是負數除外,負數和效果和3的效果一樣比3大的值也是可以的,只是效果和3一樣。
- -dvld.save_dir 指定文件輸出的路徑,默認路徑為/tmp。
- -dvld.save_paths 控制是否輸出文件,默認為0,表示不輸出文件
- -dvld.dump_paths 控制輸出的內容,現在只有0和1兩種情況,默認為1,輸出內容
- 第一章 準備工作和背景知識
- 第一節 環境搭建
- 第二節 源碼結構、閱讀代碼方法
- 第三節 常用代碼
- 第四節 小結
- 第二章 用戶代碼的執行
- 第一節 生命周期和Zend引擎
- 第二節 SAPI概述
- Apache模塊
- 嵌入式
- FastCGI
- 第三節 PHP腳本的執行
- 詞法分析和語法分析
- opcode
- opcode處理函數查找
- 第四節 小結
- 第三章 變量及數據類型
- 第一節 變量的結構和類型
- 哈希表(HashTable)
- PHP的哈希表實現
- 鏈表簡介
- 第二節 常量
- 第三節 預定義變量
- 第四節 靜態變量
- 第五節 類型提示的實現
- 第六節 變量的生命周期
- 變量的賦值和銷毀
- 變量的作用域
- global語句
- 第七節 數據類型轉換
- 第八節 小結
- 第四章 函數的實現
- 第一節 函數的內部結構
- 函數的內部結構
- 函數間的轉換
- 第二節 函數的定義,傳參及返回值
- 函數的定義
- 函數的參數
- 函數的返回值
- 第三節 函數的調用和執行
- 第四節 匿名函數及閉包
- 第五節 小結
- 第五章 類和面向對象
- 第一節 類的結構和實現
- 第二節 類的成員變量及方法
- 第三節 訪問控制的實現
- 第四節 類的繼承,多態及抽象類
- 第五節 魔術方法,延遲綁定及靜態成員
- 第六節 PHP保留類及特殊類
- 第七節 對象
- 第八節 命名空間
- 第九節 標準類
- 第十節 小結
- 第六章 內存管理
- 第一節 內存管理概述
- 第二節 PHP中的內存管理
- 第三節 內存使用:申請和銷毀
- 第四節 垃圾回收
- 新的垃圾回收
- 第五節 內存管理中的緩存
- 第六節 寫時復制(Copy On Write)
- 第七節 內存泄漏
- 第八節 小結
- 第七章 Zend虛擬機
- 第一節 Zend虛擬機概述
- 第二節 語法的實現
- 詞法解析
- 語法分析
- 實現自己的語法
- 第三節 中間代碼的執行
- 第四節 PHP代碼的加密解密
- 第五節 小結
- 第八章 線程安全
- 第二節 線程,進程和并發
- 第三節 PHP中的線程安全
- 第九章 錯誤和異常處理
- 第十章 輸出緩沖
- 第十六章 PHP語言特性的實現
- 第一節 循環語句
- foreach的實現
- 第二十章 怎么樣系列(how to)
- 附錄
- 附錄A PHP及Zend API
- 附錄B PHP的歷史
- 附錄C VLD擴展使用指南
- 附錄D 怎樣為PHP貢獻
- 附錄E phpt測試文件說明
- 附錄F PHP5.4新功能升級解析
- 附錄G:re2c中文手冊